]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/console/video_console.c
xnu-3789.21.4.tar.gz
[apple/xnu.git] / osfmk / console / video_console.c
index e696d5c308665156059073bbd94d59a02a48e7c6..5295d3c03d10e2ec3c167beb1b632a756eea6ddd 100644 (file)
@@ -441,6 +441,10 @@ gc_enable( boolean_t enable )
                                        if ( buffer_colorcodes ) kfree( buffer_colorcodes, buffer_size );
                                        if ( buffer_tab_stops  ) kfree( buffer_tab_stops,  buffer_columns );
 
+                                       buffer_attributes = NULL;
+                                       buffer_characters = NULL;
+                                       buffer_colorcodes = NULL;
+                                       buffer_tab_stops  = NULL;
                                        buffer_columns = 0;
                                        buffer_rows    = 0;
                                        buffer_size    = 0;
@@ -1856,6 +1860,9 @@ static boolean_t          vc_needsave;
 static void *                  vc_saveunder;
 static vm_size_t               vc_saveunder_len;
 static int8_t                  vc_uiscale = 1;
+vc_progress_user_options        vc_progress_options;
+vc_progress_user_options        vc_user_options;
+
 decl_simple_lock_data(,vc_progress_lock)
 
 static int                     vc_progress_withmeter = 3;
@@ -1863,6 +1870,8 @@ int                             vc_progressmeter_enable;
 static int                      vc_progressmeter_drawn;
 int                                    vc_progressmeter_value;
 static uint32_t                vc_progressmeter_count;
+static uint32_t                vc_progress_meter_start;
+static uint32_t                vc_progress_meter_end;
 static uint64_t                vc_progressmeter_interval;
 static uint64_t                vc_progressmeter_deadline;
 static thread_call_data_t      vc_progressmeter_call;
@@ -1870,6 +1879,7 @@ static void *                   vc_progressmeter_backbuffer;
 static boolean_t                vc_progressmeter_hold;
 static uint32_t                 vc_progressmeter_diskspeed = 256;
 
+
 enum {
     kSave          = 0x10,
     kDataIndexed   = 0x20,
@@ -1922,8 +1932,9 @@ static void vc_blit_rect(int x, int y, int bx,
                            void * backBuffer,
                            unsigned int flags)
 {
-    if(!vinfo.v_depth)
-        return;
+    if (!vinfo.v_depth)                                return;
+    if (((unsigned int)(x + width))  > vinfo.v_width)  return;
+    if (((unsigned int)(y + height)) > vinfo.v_height) return;
 
     switch( vinfo.v_depth) {
        case 8:
@@ -2165,9 +2176,8 @@ static void vc_blit_rect_30(int x, int y, int bx,
     {
         for( col = 0; col < width; col++)
        {
-           if (col < sourceRow)
-               data = *dataPtr++;
-
+           if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
+                               + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
            if (backPtr) {
                if (kSave & flags) {
                    back = *(dst + col);
@@ -2535,6 +2545,17 @@ vc_progress_set(boolean_t enable, uint32_t vc_delay)
 }
 
 
+static uint32_t vc_progressmeter_range(uint32_t pos)
+{
+    uint32_t ret;
+
+    if (pos > kProgressMeterEnd) pos = kProgressMeterEnd;
+    ret = vc_progress_meter_start 
+       + ((pos * (vc_progress_meter_end - vc_progress_meter_start)) / kProgressMeterEnd);
+
+    return (ret);
+}
+
 static void
 vc_progressmeter_task(__unused void *arg0, __unused void *arg)
 {
@@ -2546,7 +2567,7 @@ vc_progressmeter_task(__unused void *arg0, __unused void *arg)
     if (vc_progressmeter_enable)
     {
        uint32_t pos = (vc_progressmeter_count >> 13);
-       internal_set_progressmeter(pos);
+       internal_set_progressmeter(vc_progressmeter_range(pos));
        if (pos < kProgressMeterEnd)
        {
             static uint16_t incr[8] = { 10000, 10000, 8192, 4096, 2048, 384, 384, 64 };
@@ -2572,14 +2593,15 @@ void vc_progress_setdiskspeed(uint32_t speed)
 static void
 vc_progress_task(__unused void *arg0, __unused void *arg)
 {
-    spl_t s;
-    int                   x, y, width, height;
+    spl_t     s;
+    int              x, y, width, height;
+    uint64_t  x_pos, y_pos;
     const unsigned char * data;
 
     s = splhigh();
     simple_lock(&vc_progress_lock);
 
-    if( vc_progress_enable) {
+    if( vc_progress_enable) do {
     
        vc_progress_count++;
        if( vc_progress_count >= vc_progress->count) {
@@ -2589,32 +2611,59 @@ vc_progress_task(__unused void *arg0, __unused void *arg)
 
        width  = (vc_progress->width * vc_uiscale);
        height = (vc_progress->height * vc_uiscale);
-       x = (vc_progress->dx * vc_uiscale);
-       y = (vc_progress->dy * vc_uiscale);
-       data = vc_progress_data[vc_uiscale - 1];
-       if (data)
-        {
-           data += vc_progress_count * width * height;
+       data   = vc_progress_data[vc_uiscale - 1];
+       if (!data) break;
+
+       if (kVCUsePosition & vc_progress_options.options) {
+           /* Rotation: 0:normal, 1:right 90, 2:left 180, 3:left 90 */
+           switch (3 & vinfo.v_rotate) {
+               case 0:
+                   x_pos = vc_progress_options.x_pos;
+                   y_pos = vc_progress_options.y_pos;
+                   break;
+               case 2:
+                   x_pos = 0xFFFFFFFF - vc_progress_options.x_pos;
+                   y_pos = 0xFFFFFFFF - vc_progress_options.y_pos;
+                   break;
+               case 1:
+                   x_pos = 0xFFFFFFFF - vc_progress_options.y_pos;
+                   y_pos = vc_progress_options.x_pos;
+                   break;
+               case 3:
+                   x_pos = vc_progress_options.y_pos;
+                   y_pos = 0xFFFFFFFF - vc_progress_options.x_pos;
+                   break;
+           }
+           x = (uint32_t)((x_pos * (uint64_t) vinfo.v_width) / 0xFFFFFFFFULL);
+           y = (uint32_t)((y_pos * (uint64_t) vinfo.v_height) / 0xFFFFFFFFULL);
+           x -= (width / 2);
+           y -= (height / 2);
+       } else {
+           x = (vc_progress->dx * vc_uiscale);
+           y = (vc_progress->dy * vc_uiscale);
            if( 1 & vc_progress->flags) {
                x += ((vinfo.v_width - width) / 2);
                y += ((vinfo.v_height - height) / 2);
            }
-    
-           assert(((x + width) < (int)vinfo.v_width) && 
-                      ((y + height) < (int)vinfo.v_height));
-    
-           vc_blit_rect( x, y, 0, 
-                         width, height, width, width,
-                         data, vc_saveunder,
-                         kDataAlpha 
-                         | (vc_progress_angle & kDataRotate) 
-                         | (vc_needsave ? kSave : 0) );
-           vc_needsave = FALSE;
-
-           clock_deadline_for_periodic_event(vc_progress_interval, mach_absolute_time(), &vc_progress_deadline);
-           thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline);
        }
+
+       if ((x + width)  > (int)vinfo.v_width)  break;
+       if ((y + height) > (int)vinfo.v_height) break;
+
+       data += vc_progress_count * width * height;
+
+       vc_blit_rect( x, y, 0,
+                     width, height, width, width,
+                     data, vc_saveunder,
+                     kDataAlpha
+                     | (vc_progress_angle & kDataRotate) 
+                     | (vc_needsave ? kSave : 0) );
+       vc_needsave = FALSE;
+
+       clock_deadline_for_periodic_event(vc_progress_interval, mach_absolute_time(), &vc_progress_deadline);
+       thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline);
     }
+    while (FALSE);
     simple_unlock(&vc_progress_lock);
     splx(s);
 }
@@ -2633,10 +2682,10 @@ static boolean_t gc_graphics_boot = FALSE;
 static boolean_t gc_desire_text   = FALSE;
 static boolean_t gc_paused_progress;
 
-static uint64_t lastVideoPhys   = 0;
-static vm_offset_t  lastVideoVirt   = 0;
-static vm_size_t lastVideoSize   = 0;
-static boolean_t    lastVideoMapped = FALSE;
+static vm_offset_t  lastVideoVirt    = 0;
+static vm_size_t    lastVideoMapSize = 0;
+static boolean_t    lastVideoMapKmap = FALSE;
+
 static void
 gc_pause( boolean_t pause, boolean_t graphics_now )
 {
@@ -2685,28 +2734,29 @@ vc_initialize(__unused struct vc_info * vinfo_p)
 void
 initialize_screen(PE_Video * boot_vinfo, unsigned int op)
 {
-       unsigned int fbsize = 0;
+       unsigned int newMapSize = 0;
        vm_offset_t newVideoVirt = 0;
        boolean_t graphics_now;
-       ppnum_t fbppage;
+       uint32_t delay;
 
        if ( boot_vinfo )
        {
                struct vc_info new_vinfo = vinfo;
+               boolean_t makeMapping = FALSE;
+
                /* 
-                *      First, check if we are changing the size and/or location of the framebuffer
+                *      Copy parameters
                 */
-               new_vinfo.v_name[0]  = 0;
-               new_vinfo.v_physaddr = boot_vinfo->v_baseAddr & ~3;             /* Get the physical address */
-#ifndef __LP64__
-               new_vinfo.v_physaddr |= (((uint64_t) boot_vinfo->v_baseAddrHigh) << 32);
-#endif
                if (kPEBaseAddressChange != op)
                {
                    new_vinfo.v_width    = (unsigned int)boot_vinfo->v_width;
                    new_vinfo.v_height   = (unsigned int)boot_vinfo->v_height;
                    new_vinfo.v_depth    = (unsigned int)boot_vinfo->v_depth;
                    new_vinfo.v_rowbytes = (unsigned int)boot_vinfo->v_rowBytes;
+                   if (kernel_map == VM_MAP_NULL) {
+                               // only booter supplies HW rotation
+                               new_vinfo.v_rotate   = (unsigned int)boot_vinfo->v_rotate;
+                   }
 #if defined(__i386__) || defined(__x86_64__)
                    new_vinfo.v_type     = (unsigned int)boot_vinfo->v_display;
 #else
@@ -2719,14 +2769,28 @@ initialize_screen(PE_Video * boot_vinfo, unsigned int op)
                 new_vinfo.v_scale = kPEScaleFactor2x;
             else /* Scale factor not set, default to 1x */
                 new_vinfo.v_scale = kPEScaleFactor1x;
+               }
+               new_vinfo.v_name[0]  = 0;
+               new_vinfo.v_physaddr = 0;
 
+               /*
+                *  Check if we are have to map the framebuffer
+                *  If VM is up, we are given a virtual address, unless b0 is set to indicate physical.
+                */
+               newVideoVirt = boot_vinfo->v_baseAddr;
+               makeMapping = (kernel_map == VM_MAP_NULL) || (0 != (1 & newVideoVirt));
+               if (makeMapping)
+               {
+                       newVideoVirt = 0;
+                       new_vinfo.v_physaddr = boot_vinfo->v_baseAddr & ~3UL;           /* Get the physical address */
+#ifndef __LP64__
+                       new_vinfo.v_physaddr |= (((uint64_t) boot_vinfo->v_baseAddrHigh) << 32);
+#endif
+                       kprintf("initialize_screen: b=%08llX, w=%08X, h=%08X, r=%08X, d=%08X\n",                  /* (BRINGUP) */
+                           new_vinfo.v_physaddr, new_vinfo.v_width,  new_vinfo.v_height,  new_vinfo.v_rowbytes, new_vinfo.v_type);     /* (BRINGUP) */
                }
      
-               if (!lastVideoMapped)
-                   kprintf("initialize_screen: b=%08llX, w=%08X, h=%08X, r=%08X, d=%08X\n",                  /* (BRINGUP) */
-                           new_vinfo.v_physaddr, new_vinfo.v_width,  new_vinfo.v_height,  new_vinfo.v_rowbytes, new_vinfo.v_type);     /* (BRINGUP) */
-
-               if (!new_vinfo.v_physaddr)                                                      /* Check to see if we have a framebuffer */
+               if (!newVideoVirt && !new_vinfo.v_physaddr)                                                     /* Check to see if we have a framebuffer */
                {
                        kprintf("initialize_screen: No video - forcing serial mode\n");         /* (BRINGUP) */
                        new_vinfo.v_depth = 0;                                          /* vc routines are nop */
@@ -2737,36 +2801,17 @@ initialize_screen(PE_Video * boot_vinfo, unsigned int op)
                }
                else
                {
-                   /*
-                    * If VM is up, we are given a virtual address, unless b0 is set to indicate physical.
-                    */
-                       if ((kernel_map != VM_MAP_NULL) && (0 == (1 & boot_vinfo->v_baseAddr)))
-                   {
-                           fbppage = pmap_find_phys(kernel_pmap, (addr64_t)boot_vinfo->v_baseAddr);    /* Get the physical address of frame buffer */
-                           if(!fbppage)                                                /* Did we find it? */
-                           {
-                                   panic("initialize_screen: Strange framebuffer - addr = %08X\n", (uint32_t)boot_vinfo->v_baseAddr);
-                           }
-                           new_vinfo.v_physaddr = (((uint64_t)fbppage) << PAGE_SHIFT) | (boot_vinfo->v_baseAddr & PAGE_MASK);                  /* Get the physical address */
-                   }
-    
-                   if (boot_vinfo->v_length != 0)
-                           fbsize = (unsigned int) round_page(boot_vinfo->v_length);
-                   else
-                           fbsize = (unsigned int) round_page(new_vinfo.v_height * new_vinfo.v_rowbytes);                      /* Remember size */
-
-    
-                   if ((lastVideoPhys != new_vinfo.v_physaddr) || (fbsize > lastVideoSize))            /* Did framebuffer change location or get bigger? */
+                   if (makeMapping)
                    {
                            unsigned int flags = VM_WIMG_IO;
-                           newVideoVirt = io_map_spec((vm_map_offset_t)new_vinfo.v_physaddr, fbsize, flags);   /* Allocate address space for framebuffer */
-                   }
-               }
-
-               if (newVideoVirt != 0)
+                               if (boot_vinfo->v_length != 0)
+                                       newMapSize = (unsigned int) round_page(boot_vinfo->v_length);
+                               else
+                                       newMapSize = (unsigned int) round_page(new_vinfo.v_height * new_vinfo.v_rowbytes);                      /* Remember size */
+                           newVideoVirt = io_map_spec((vm_map_offset_t)new_vinfo.v_physaddr, newMapSize, flags);       /* Allocate address space for framebuffer */
+                       }
                    new_vinfo.v_baseaddr = newVideoVirt + boot_vinfo->v_offset;                         /* Set the new framebuffer address */
-               else
-                   new_vinfo.v_baseaddr = lastVideoVirt + boot_vinfo->v_offset;                                /* Set the new framebuffer address */
+               }
 
 #if defined(__x86_64__)
                // Adjust the video buffer pointer to point to where it is in high virtual (above the hole)
@@ -2788,24 +2833,23 @@ initialize_screen(PE_Video * boot_vinfo, unsigned int op)
                // If we changed the virtual address, remove the old mapping
                if (newVideoVirt != 0)
                {
-                       if (lastVideoVirt)                                                      /* Was the framebuffer mapped before? */
+                       if (lastVideoVirt && lastVideoMapSize)                                                  /* Was the framebuffer mapped before? */
                        {
-                               /* XXX why did this ever succeed? */
-                               /* TODO: Consider this. */
-                               if (!TEST_PAGE_SIZE_4K && lastVideoMapped)      /* Was this not a special pre-VM mapping? */
+                               /* XXX why only !4K? */
+                               if (!TEST_PAGE_SIZE_4K && lastVideoMapSize)
                                {
                                        pmap_remove(kernel_pmap, trunc_page_64(lastVideoVirt),
-                                               round_page_64(lastVideoVirt + lastVideoSize));  /* Toss mappings */
+                                               round_page_64(lastVideoVirt + lastVideoMapSize));       /* Toss mappings */
                                }
-                               if(lastVideoMapped)                            /* Was this not a special pre-VM mapping? */
+                               /* Was this not a special pre-VM mapping? */
+                               if (lastVideoMapKmap)
                                {
-                                       kmem_free(kernel_map, lastVideoVirt, lastVideoSize);    /* Toss kernel addresses */
+                                       kmem_free(kernel_map, lastVideoVirt, lastVideoMapSize); /* Toss kernel addresses */
                                }
                        }
-                       lastVideoPhys = new_vinfo.v_physaddr;                                   /* Remember the framebuffer address */
-                       lastVideoSize = fbsize;                                                 /* Remember the size */
-                       lastVideoVirt = newVideoVirt;                                           /* Remember the virtual framebuffer address */
-                       lastVideoMapped  = (NULL != kernel_map);
+                       lastVideoMapKmap = (NULL != kernel_map);                /* Remember how mapped */
+                       lastVideoMapSize = newMapSize;                                  /* Remember the size */
+                       lastVideoVirt    = newVideoVirt;                                /* Remember the virtual framebuffer address */
                }
 
         if (kPEBaseAddressChange != op)
@@ -2840,7 +2884,18 @@ initialize_screen(PE_Video * boot_vinfo, unsigned int op)
 
                case kPEAcquireScreen:
                        if ( gc_acquired ) break;
-                       vc_progress_set( graphics_now, vc_acquire_delay );
+
+                       vc_progress_options = vc_user_options;
+                       bzero(&vc_user_options, sizeof(vc_user_options));
+
+                       if (kVCAcquireImmediate & vc_progress_options.options) delay = 0;
+                       else if (kVCDarkReboot & vc_progress_options.options)  delay = 120;
+                       else                                                   delay = vc_acquire_delay;
+
+                       if (kVCDarkBackground & vc_progress_options.options)       vc_progress_white = TRUE;
+                       else if (kVCLightBackground & vc_progress_options.options) vc_progress_white = FALSE;
+
+                       vc_progress_set( graphics_now, delay );
                        gc_enable( !graphics_now );
                        gc_acquired = TRUE;
                        gc_desire_text = FALSE;
@@ -2884,8 +2939,8 @@ initialize_screen(PE_Video * boot_vinfo, unsigned int op)
 
                        vc_progress_set( FALSE, 0 );
                        vc_acquire_delay = kProgressReacquireDelay;
-                       vc_enable_progressmeter(FALSE);
                        vc_progress_white      = TRUE;
+                       vc_enable_progressmeter(FALSE);
                        vc_progress_withmeter &= ~1;
                        vc_clut8 = NULL;
                        break;
@@ -2907,7 +2962,7 @@ initialize_screen(PE_Video * boot_vinfo, unsigned int op)
                    simple_lock(&vc_progress_lock);
 
                    vc_progressmeter_drawn = 0;
-                   internal_set_progressmeter(vc_progressmeter_count >> 13);
+                   internal_set_progressmeter(vc_progressmeter_range(vc_progressmeter_count >> 13));
 
                    simple_unlock(&vc_progress_lock);
                    splx(s);
@@ -2918,39 +2973,6 @@ initialize_screen(PE_Video * boot_vinfo, unsigned int op)
        }
 }
 
-void 
-dim_screen(void)
-{
-       unsigned int *p, *endp, *row;
-       int      col, rowline, rowlongs;
-       register unsigned int mask;
-
-       if(!vinfo.v_depth)
-               return;
-
-       if ( vinfo.v_depth == 32 )
-               mask = 0x007F7F7F;
-       else if ( vinfo.v_depth == 30 )
-               mask = (0x1ff<<20) | (0x1ff<<10) | 0x1ff;
-       else if ( vinfo.v_depth == 16 )
-               mask = 0x3DEF3DEF;
-       else
-               return;
-
-       rowline = (int)(vinfo.v_rowscanbytes / 4);
-       rowlongs = (int)(vinfo.v_rowbytes / 4);
-
-       p = (unsigned int*) vinfo.v_baseaddr;
-       endp = p + (rowlongs * vinfo.v_height);
-
-       for (row = p ; row < endp ; row += rowlongs) {
-               for (p = &row[0], col = 0; col < rowline; col++) {
-                       *p = (*p >> 1) & mask;
-                       ++p;
-               }
-       }
-}
-
 void vcattach(void); /* XXX gcc 4 warning cleanup */
 
 void
@@ -2958,9 +2980,22 @@ vcattach(void)
 {
        vm_initialized = TRUE;
 
+        const boot_args * bootargs  = (typeof(bootargs)) PE_state.bootArgs;
+
        vc_progress_white = (0 != ((kBootArgsFlagBlackBg | kBootArgsFlagLoginUI) 
-                                         & ((boot_args *) PE_state.bootArgs)->flags));
+                                         & bootargs->flags));
        PE_parse_boot_argn("meter", &vc_progress_withmeter, sizeof(vc_progress_withmeter));
+
+       if (kBootArgsFlagInstallUI & bootargs->flags)
+       {
+           vc_progress_meter_start = (bootargs->bootProgressMeterStart * kProgressMeterMax) / 65535;
+           vc_progress_meter_end   = (bootargs->bootProgressMeterEnd   * kProgressMeterMax) / 65535;
+       }
+       else
+       {
+           vc_progress_meter_start = 0;
+           vc_progress_meter_end   = kProgressMeterMax;
+       }
        simple_lock_init(&vc_progress_lock, 0);
 
        if ( gc_graphics_boot == FALSE )
@@ -3190,3 +3225,5 @@ vc_set_progressmeter(int new_value)
 }
 
 
+
+