X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/060df5ea7c632b1ac8cc8aac1fb59758165c2084..d9a64523371fa019c4575bb400cbbc3a50ac9903:/osfmk/console/video_console.c diff --git a/osfmk/console/video_console.c b/osfmk/console/video_console.c index 4b088aa41..52d956da3 100644 --- a/osfmk/console/video_console.c +++ b/osfmk/console/video_console.c @@ -88,15 +88,12 @@ * */ -#include - #include #include #include #include #include -#include #include #include @@ -121,11 +118,10 @@ */ struct vc_info vinfo; -/* if panicDialogDesired is true then we use the panic dialog when its */ -/* allowed otherwise we won't use the panic dialog even if it is allowed */ -boolean_t panicDialogDesired; - +void noroot_icon_test(void); + + extern int disableConsoleOutput; static boolean_t gc_enabled = FALSE; static boolean_t gc_initialized = FALSE; @@ -187,7 +183,7 @@ MACRO_END #define VCPUTC_LOCK_LOCK() \ MACRO_BEGIN \ - if (!hw_lock_to(&vcputc_lock, LockTimeOut*10)) \ + if (!hw_lock_to(&vcputc_lock, ~0U))\ { \ panic("VCPUTC_LOCK_LOCK"); \ } \ @@ -229,12 +225,6 @@ static unsigned int gc_par[MAXPARS], gc_numpars, gc_hanging_cursor, gc_attr, gc_ /* VT100 scroll region */ static unsigned int gc_scrreg_top, gc_scrreg_bottom; -#ifdef CONFIG_VC_PROGRESS_WHITE -enum { kProgressAcquireDelay = 0 /* secs */ }; -#else -enum { kProgressAcquireDelay = 5 /* secs */ }; -#endif - enum vt100state_e { ESnormal, /* Nothing yet */ ESesc, /* Got ESC */ @@ -250,6 +240,29 @@ enum vt100state_e { ESignore /* Ignore this sequence */ } gc_vt100state = ESnormal; + +enum +{ + /* secs */ + kProgressAcquireDelay = 0, +#if CONFIG_EMBEDDED + kProgressReacquireDelay = 5, +#else + kProgressReacquireDelay = 5, +#endif +}; + +static int8_t vc_rotate_matr[4][2][2] = { + { { 1, 0 }, + { 0, 1 } }, + { { 0, 1 }, + { -1, 0 } }, + { { -1, 0 }, + { 0, -1 } }, + { { 0, -1 }, + { 1, 0 } } +}; + static int gc_wrap_mode = 1, gc_relative_origin = 0; static int gc_charset_select = 0, gc_save_charset_s = 0; static int gc_charset[2] = { 0, 0 }; @@ -434,6 +447,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; @@ -1267,6 +1284,8 @@ gc_show_cursor(unsigned int xx, unsigned int yy) static void gc_update_color(int color, boolean_t fore) { + assert(gc_ops.update_color); + gc_color_code = COLOR_CODE_SET(gc_color_code, color, fore); gc_ops.update_color(color, fore); } @@ -1274,7 +1293,7 @@ gc_update_color(int color, boolean_t fore) void vcputc(__unused int l, __unused int u, int c) { - if ( gc_enabled || debug_mode ) + if ( gc_initialized && gc_enabled ) { spl_t s; @@ -1283,7 +1302,7 @@ vcputc(__unused int l, __unused int u, int c) x86_filter_TLB_coherency_interrupts(TRUE); #endif VCPUTC_LOCK_LOCK(); - if ( gc_enabled || debug_mode ) + if ( gc_enabled ) { gc_hide_cursor(gc_x, gc_y); gc_putchar(c); @@ -1340,6 +1359,35 @@ static int vc_rendered_char_size = 0; #define REN_MAX_DEPTH 32 static unsigned char vc_rendered_char[ISO_CHAR_HEIGHT * ((REN_MAX_DEPTH / 8) * ISO_CHAR_WIDTH)]; +#if !CONFIG_EMBEDDED +static void +internal_set_progressmeter(int new_value); +static void +internal_enable_progressmeter(int new_value); + +enum +{ + kProgressMeterOff = FALSE, + kProgressMeterUser = TRUE, + kProgressMeterKernel = 3, +}; +enum +{ + kProgressMeterMax = 1024, + kProgressMeterEnd = 512, +}; + +#endif /* !CONFIG_EMBEDDED */ + +static boolean_t vc_progress_white = +#ifdef CONFIG_VC_PROGRESS_WHITE + TRUE; +#else /* !CONFIG_VC_PROGRESS_WHITE */ + FALSE; +#endif /* !CONFIG_VC_PROGRESS_WHITE */ + +static int vc_acquire_delay = kProgressAcquireDelay; + static void vc_clear_screen(unsigned int xx, unsigned int yy, unsigned int scrreg_top, unsigned int scrreg_bottom, int which) @@ -1389,15 +1437,6 @@ vc_clear_screen(unsigned int xx, unsigned int yy, unsigned int scrreg_top, } } -static void -vc_initialize(__unused struct vc_info * vinfo_p) -{ - - vinfo.v_rows = vinfo.v_height / ISO_CHAR_HEIGHT; - vinfo.v_columns = vinfo.v_width / ISO_CHAR_WIDTH; - vinfo.v_rowscanbytes = ((vinfo.v_depth + 7) / 8) * vinfo.v_width; -} - static void vc_render_char(unsigned char ch, unsigned char *renderptr, short newdepth) { @@ -1812,24 +1851,9 @@ vc_update_color(int color, boolean_t fore) * -------------------------------------- */ -struct vc_progress_element { - unsigned int version; - unsigned int flags; - unsigned int time; - unsigned char count; - unsigned char res[3]; - int width; - int height; - int dx; - int dy; - int transparent; - unsigned int res2[3]; - unsigned char data[0]; -}; -typedef struct vc_progress_element vc_progress_element; - static vc_progress_element * vc_progress; -static const unsigned char * vc_progress_data; +enum { kMaxProgressData = 3 }; +static const unsigned char * vc_progress_data[kMaxProgressData]; static const unsigned char * vc_progress_alpha; static boolean_t vc_progress_enable; static const unsigned char * vc_clut; @@ -1837,18 +1861,45 @@ static const unsigned char * vc_clut8; static unsigned char vc_revclut8[256]; static uint32_t vc_progress_interval; static uint32_t vc_progress_count; +static uint32_t vc_progress_angle; static uint64_t vc_progress_deadline; static thread_call_data_t vc_progress_call; 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) +#if !CONFIG_EMBEDDED +static int vc_progress_withmeter = 3; +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; +static void * vc_progressmeter_backbuffer; +static boolean_t vc_progressmeter_hold; +static uint32_t vc_progressmeter_diskspeed = 256; + +#endif /* !CONFIG_EMBEDDED */ + enum { - kSave = 0x01, - kDataIndexed = 0x02, - kDataAlpha = 0x04, - kDataBack = 0x08, + kSave = 0x10, + kDataIndexed = 0x20, + kDataAlpha = 0x40, + kDataBack = 0x80, + kDataRotate = 0x03, + kDataRotate0 = 0, + kDataRotate90 = 1, + kDataRotate180 = 2, + kDataRotate270 = 3 }; static void vc_blit_rect(int x, int y, int bx, @@ -1881,10 +1932,10 @@ static void vc_blit_rect_30(int x, int y, int bx, const unsigned char * dataPtr, unsigned int * backBuffer, unsigned int flags); -extern void vc_display_icon( vc_progress_element * desc, const unsigned char * data ); -extern void vc_progress_initialize( vc_progress_element * desc, const unsigned char * data, const unsigned char * clut ); -void vc_progress_set(boolean_t enable, uint32_t vc_delay); static void vc_progress_task( void * arg0, void * arg ); +#if !CONFIG_EMBEDDED +static void vc_progressmeter_task( void * arg0, void * arg ); +#endif /* !CONFIG_EMBEDDED */ static void vc_blit_rect(int x, int y, int bx, int width, int height, @@ -1893,8 +1944,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: @@ -1924,9 +1976,19 @@ vc_blit_rect_8(int x, int y, __unused int bx, volatile unsigned short * dst; int line, col; unsigned int data = 0, out = 0; + int sx, sy, a, b, c, d; + int scale = 0x10000; + + a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; + b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; + c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; + d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; + sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; + sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; + + if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; + else if (1 == sourceRow) a = 0; - if (!sourceRow) - data = (unsigned int)(uintptr_t)dataPtr; dst = (volatile unsigned short *) (vinfo.v_baseaddr + (y * vinfo.v_rowbytes) + (x * 4)); @@ -1935,8 +1997,8 @@ vc_blit_rect_8(int x, int y, __unused 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 (kDataAlpha & flags) out = vc_revclut8[data]; else @@ -1944,13 +2006,25 @@ vc_blit_rect_8(int x, int y, __unused int bx, *(dst + col) = out; } dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes); - if (sourceRow > width) - dataPtr += sourceRow - width; } } /* For ARM, 16-bit is 565 (RGB); it is 1555 (XRGB) on other platforms */ +#ifdef __arm__ +#define CLUT_MASK_R 0xf8 +#define CLUT_MASK_G 0xfc +#define CLUT_MASK_B 0xf8 +#define CLUT_SHIFT_R << 8 +#define CLUT_SHIFT_G << 3 +#define CLUT_SHIFT_B >> 3 +#define MASK_R 0xf800 +#define MASK_G 0x07e0 +#define MASK_B 0x001f +#define MASK_R_8 0x7f800 +#define MASK_G_8 0x01fe0 +#define MASK_B_8 0x000ff +#else #define CLUT_MASK_R 0xf8 #define CLUT_MASK_G 0xf8 #define CLUT_MASK_B 0xf8 @@ -1963,6 +2037,7 @@ vc_blit_rect_8(int x, int y, __unused int bx, #define MASK_R_8 0x3fc00 #define MASK_G_8 0x01fe0 #define MASK_B_8 0x000ff +#endif static void vc_blit_rect_16( int x, int y, int bx, int width, int height, @@ -1974,11 +2049,21 @@ static void vc_blit_rect_16( int x, int y, int bx, volatile unsigned short * dst; int line, col; unsigned int data = 0, out = 0, back = 0; + int sx, sy, a, b, c, d; + int scale = 0x10000; + + a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; + b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; + c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; + d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; + sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; + sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; + + if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; + else if (1 == sourceRow) a = 0; if (backPtr) backPtr += bx; - if (!sourceRow) - data = (unsigned int)(uintptr_t)dataPtr; dst = (volatile unsigned short *) (vinfo.v_baseaddr + (y * vinfo.v_rowbytes) + (x * 2)); @@ -1987,9 +2072,8 @@ static void vc_blit_rect_16( 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); @@ -2005,23 +2089,22 @@ static void vc_blit_rect_16( int x, int y, int bx, out = (((((back & MASK_R) * data) + MASK_R_8) >> 8) & MASK_R) | (((((back & MASK_G) * data) + MASK_G_8) >> 8) & MASK_G) | (((((back & MASK_B) * data) + MASK_B_8) >> 8) & MASK_B); -#ifdef CONFIG_VC_PROGRESS_WHITE - out += (((0xff - data) & CLUT_MASK_R) CLUT_SHIFT_R) - | (((0xff - data) & CLUT_MASK_G) CLUT_SHIFT_G) - | (((0xff - data) & CLUT_MASK_B) CLUT_SHIFT_B); -#endif - } else + if (vc_progress_white) out += (((0xff - data) & CLUT_MASK_R) CLUT_SHIFT_R) + | (((0xff - data) & CLUT_MASK_G) CLUT_SHIFT_G) + | (((0xff - data) & CLUT_MASK_B) CLUT_SHIFT_B); + } else if (kDataBack & flags) out = back; + else + out = data; *(dst + col) = out; } dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes); if (backPtr) backPtr += backRow - width; - if (sourceRow > width) - dataPtr += sourceRow - width; } } + static void vc_blit_rect_32(int x, int y, int bx, int width, int height, int sourceRow, int backRow, @@ -2032,11 +2115,21 @@ static void vc_blit_rect_32(int x, int y, int bx, volatile unsigned int * dst; int line, col; unsigned int data = 0, out = 0, back = 0; - + int sx, sy, a, b, c, d; + int scale = 0x10000; + + a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; + b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; + c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; + d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; + sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; + sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; + + if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; + else if (1 == sourceRow) a = 0; + if (backPtr) backPtr += bx; - if (!sourceRow) - data = (unsigned int)(uintptr_t)dataPtr; dst = (volatile unsigned int *) (vinfo.v_baseaddr + (y * vinfo.v_rowbytes) + (x * 4)); @@ -2045,9 +2138,8 @@ static void vc_blit_rect_32(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); @@ -2062,20 +2154,18 @@ static void vc_blit_rect_32(int x, int y, int bx, } else if (kDataAlpha & flags) { out = (((((back & 0x00ff00ff) * data) + 0x00ff00ff) >> 8) & 0x00ff00ff) | (((((back & 0x0000ff00) * data) + 0x0000ff00) >> 8) & 0x0000ff00); -#ifdef CONFIG_VC_PROGRESS_WHITE - out += ((0xff - data) << 16) - | ((0xff - data) << 8) - | (0xff - data); -#endif - } else + if (vc_progress_white) out += ((0xff - data) << 16) + | ((0xff - data) << 8) + | (0xff - data); + } else if (kDataBack & flags) out = back; + else + out = data; *(dst + col) = out; } dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes); if (backPtr) backPtr += backRow - width; - if (sourceRow > width) - dataPtr += sourceRow - width; } } @@ -2090,11 +2180,21 @@ static void vc_blit_rect_30(int x, int y, int bx, int line, col; unsigned int data = 0, out = 0, back = 0; unsigned long long exp; - + int sx, sy, a, b, c, d; + int scale = 0x10000; + + a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; + b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; + c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; + d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; + sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; + sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; + + if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; + else if (1 == sourceRow) a = 0; + if (backPtr) backPtr += bx; - if (!sourceRow) - data = (unsigned int)(uintptr_t)dataPtr; dst = (volatile unsigned int *) (vinfo.v_baseaddr + (y * vinfo.v_rowbytes) + (x * 4)); @@ -2103,9 +2203,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); @@ -2122,23 +2221,177 @@ static void vc_blit_rect_30(int x, int y, int bx, exp = (((((exp & 0x3FF003FF) * data) + 0x0FF000FF) >> 8) & 0x3FF003FF) | (((((exp & 0x000FFC00) * data) + 0x0003FC00) >> 8) & 0x000FFC00); out = (unsigned int)exp; -#ifdef CONFIG_VC_PROGRESS_WHITE - out += ((0xFF - data) << 22) - | ((0xFF - data) << 12) - | ((0xFF - data) << 2); -#endif - } else + if (vc_progress_white) out += ((0xFF - data) << 22) + | ((0xFF - data) << 12) + | ((0xFF - data) << 2); + } else if (kDataBack & flags) out = back; + else + out = data; *(dst + col) = out; } dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes); if (backPtr) backPtr += backRow - width; - if (sourceRow > width) - dataPtr += sourceRow - width; } } +static void vc_clean_boot_graphics(void) +{ +#if !CONFIG_EMBEDDED + // clean up possible FDE login graphics + vc_progress_set(FALSE, 0); + const unsigned char * + color = (typeof(color))(uintptr_t)(vc_progress_white ? 0x00000000 : 0xBFBFBFBF); + vc_blit_rect(0, 0, 0, vinfo.v_width, vinfo.v_height, 0, 0, color, NULL, 0); +#endif +} + +/* + * Routines to render the lzss image format + */ + +struct lzss_image_state { + uint32_t col; + uint32_t row; + uint32_t width; + uint32_t height; + uint32_t bytes_per_row; + volatile uint32_t * row_start; + const uint8_t* clut; +}; +typedef struct lzss_image_state lzss_image_state; + +// returns 0 if OK, 1 if error +static inline int +vc_decompress_lzss_next_pixel (int next_data, lzss_image_state* state) +{ + uint32_t palette_index = 0; + uint32_t pixel_value = 0; + + palette_index = next_data * 3; + + pixel_value = ( (uint32_t) state->clut[palette_index + 0] << 16) + | ( (uint32_t) state->clut[palette_index + 1] << 8) + | ( (uint32_t) state->clut[palette_index + 2]); + + *(state->row_start + state->col) = pixel_value; + + if (++state->col >= state->width) { + state->col = 0; + if (++state->row >= state->height) { + return 1; + } + state->row_start = (volatile uint32_t *) (((uintptr_t)state->row_start) + state->bytes_per_row); + } + return 0; +} + + +/* + * Blit an lzss compressed image to the framebuffer + * Assumes 32 bit screen (which is everything we ship at the moment) + * The function vc_display_lzss_icon was copied from libkern/mkext.c, then modified. + */ + +/* + * TODO: Does lzss use too much stack? 4096 plus bytes... + * Can probably chop it down by 1/2. + */ + +/************************************************************** + LZSS.C -- A Data Compression Program +*************************************************************** + 4/6/1989 Haruhiko Okumura + Use, distribute, and modify this program freely. + Please send me your improved versions. + PC-VAN SCIENCE + NIFTY-Serve PAF01022 + CompuServe 74050,1022 + +**************************************************************/ + +#define N 4096 /* size of ring buffer - must be power of 2 */ +#define F 18 /* upper limit for match_length */ +#define THRESHOLD 2 /* encode string into position and length + if match_length is greater than this */ + +// returns 0 if OK, 1 if error +// x and y indicate upper left corner of image location on screen +int +vc_display_lzss_icon(uint32_t dst_x, uint32_t dst_y, + uint32_t image_width, uint32_t image_height, + const uint8_t *compressed_image, + uint32_t compressed_size, + const uint8_t *clut) +{ + uint32_t* image_start; + uint32_t bytes_per_pixel = 4; + uint32_t bytes_per_row = vinfo.v_rowbytes; + + vc_clean_boot_graphics(); + + image_start = (uint32_t *) (vinfo.v_baseaddr + (dst_y * bytes_per_row) + (dst_x * bytes_per_pixel)); + + lzss_image_state state = {0, 0, image_width, image_height, bytes_per_row, image_start, clut}; + + int rval = 0; + + const uint8_t *src = compressed_image; + uint32_t srclen = compressed_size; + + /* ring buffer of size N, with extra F-1 bytes to aid string comparison */ + uint8_t text_buf[N + F - 1]; + const uint8_t *srcend = src + srclen; + int i, j, k, r, c; + unsigned int flags; + + srcend = src + srclen; + for (i = 0; i < N - F; i++) + text_buf[i] = ' '; + r = N - F; + flags = 0; + for ( ; ; ) { + if (((flags >>= 1) & 0x100) == 0) { + if (src < srcend) c = *src++; else break; + flags = c | 0xFF00; /* uses higher byte cleverly */ + } /* to count eight */ + if (flags & 1) { + if (src < srcend) c = *src++; else break; + rval = vc_decompress_lzss_next_pixel(c, &state); + if (rval != 0) + return rval; + text_buf[r++] = c; + r &= (N - 1); + } else { + if (src < srcend) i = *src++; else break; + if (src < srcend) j = *src++; else break; + i |= ((j & 0xF0) << 4); + j = (j & 0x0F) + THRESHOLD; + for (k = 0; k <= j; k++) { + c = text_buf[(i + k) & (N - 1)]; + rval = vc_decompress_lzss_next_pixel(c, &state); + if (rval != 0 ) + return rval; + text_buf[r++] = c; + r &= (N - 1); + } + } + } + return 0; +} + +void noroot_icon_test(void) { + boolean_t o_vc_progress_enable = vc_progress_enable; + + vc_progress_enable = 1; + + PE_display_icon( 0, "noroot"); + + vc_progress_enable = o_vc_progress_enable; +} + + void vc_display_icon( vc_progress_element * desc, const unsigned char * data ) { @@ -2146,6 +2399,8 @@ void vc_display_icon( vc_progress_element * desc, if( vc_progress_enable && vc_clut) { + vc_clean_boot_graphics(); + width = desc->width; height = desc->height; x = desc->dx; @@ -2160,30 +2415,38 @@ void vc_display_icon( vc_progress_element * desc, void vc_progress_initialize( vc_progress_element * desc, - const unsigned char * data, + const unsigned char * data1x, + const unsigned char * data2x, + const unsigned char * data3x, const unsigned char * clut ) { - uint64_t abstime; + uint64_t abstime; - if( (!clut) || (!desc) || (!data)) + if( (!clut) || (!desc) || (!data1x)) return; vc_clut = clut; vc_clut8 = clut; - simple_lock_init(&vc_progress_lock, 0); - vc_progress = desc; - vc_progress_data = data; + vc_progress_data[0] = data1x; + vc_progress_data[1] = data2x; + vc_progress_data[2] = data3x; if( 2 & vc_progress->flags) - vc_progress_alpha = vc_progress_data + vc_progress_alpha = data1x + vc_progress->count * vc_progress->width * vc_progress->height; else vc_progress_alpha = NULL; thread_call_setup(&vc_progress_call, vc_progress_task, NULL); - clock_interval_to_absolutetime_interval(vc_progress->time, 1000 * 1000, &abstime); vc_progress_interval = (uint32_t)abstime; + +#if !CONFIG_EMBEDDED + thread_call_setup(&vc_progressmeter_call, vc_progressmeter_task, NULL); + clock_interval_to_absolutetime_interval(1000 / 8, 1000 * 1000, &abstime); + vc_progressmeter_interval = (uint32_t)abstime; +#endif /* !CONFIG_EMBEDDED */ + } void @@ -2200,11 +2463,43 @@ vc_progress_set(boolean_t enable, uint32_t vc_delay) unsigned int pdata32; unsigned int * buf32; - if( !vc_progress) +#if !CONFIG_EMBEDDED + + if (kBootArgsFlagBlack & ((boot_args *) PE_state.bootArgs)->flags) return; + + if (1 & vc_progress_withmeter) + { + if (enable) internal_enable_progressmeter(kProgressMeterKernel); + + s = splhigh(); + simple_lock(&vc_progress_lock); + + if( vc_progress_enable != enable) { + vc_progress_enable = enable; + if( enable) + { + vc_progressmeter_count = 0; + clock_interval_to_deadline(vc_delay, + 1000 * 1000 * 1000 /*second scale*/, + &vc_progressmeter_deadline); + thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline); + } + else thread_call_cancel(&vc_progressmeter_call); + } + + simple_unlock(&vc_progress_lock); + splx(s); + + if (!enable) internal_enable_progressmeter(kProgressMeterOff); return; + } + +#endif /* !CONFIG_EMBEDDED */ + + if(!vc_progress) return; if( enable) { - saveLen = vc_progress->width * vc_progress->height * vinfo.v_depth / 8; + saveLen = (vc_progress->width * vc_uiscale) * (vc_progress->height * vc_uiscale) * ((vinfo.v_depth + 7) / 8); saveBuf = kalloc( saveLen ); switch( vinfo.v_depth) { @@ -2256,6 +2551,7 @@ vc_progress_set(boolean_t enable, uint32_t vc_delay) saveBuf = NULL; saveLen = 0; vc_progress_count = 0; + vc_progress_angle = 0; clock_interval_to_deadline(vc_delay, 1000 * 1000 * 1000 /*second scale*/, @@ -2281,44 +2577,128 @@ vc_progress_set(boolean_t enable, uint32_t vc_delay) kfree( saveBuf, saveLen ); } +#if !CONFIG_EMBEDDED + +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) +{ + spl_t s; + uint64_t interval; + + s = splhigh(); + simple_lock(&vc_progress_lock); + if (vc_progressmeter_enable) + { + uint32_t pos = (vc_progressmeter_count >> 13); + internal_set_progressmeter(vc_progressmeter_range(pos)); + if (pos < kProgressMeterEnd) + { + static uint16_t incr[8] = { 10000, 10000, 8192, 4096, 2048, 384, 384, 64 }; + vc_progressmeter_count += incr[(pos * 8) / kProgressMeterEnd]; + + interval = vc_progressmeter_interval; + interval = ((interval * 256) / vc_progressmeter_diskspeed); + + clock_deadline_for_periodic_event(interval, mach_absolute_time(), &vc_progressmeter_deadline); + thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline); + } + } + simple_unlock(&vc_progress_lock); + splx(s); +} + +void vc_progress_setdiskspeed(uint32_t speed) +{ + vc_progressmeter_diskspeed = speed; +} + +#endif /* !CONFIG_EMBEDDED */ 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) { - - KERNEL_DEBUG_CONSTANT(0x7020008, vc_progress_count, 0, 0, 0, 0); + if( vc_progress_enable) do { + + vc_progress_count++; + if( vc_progress_count >= vc_progress->count) { + vc_progress_count = 0; + vc_progress_angle++; + } + + width = (vc_progress->width * vc_uiscale); + height = (vc_progress->height * vc_uiscale); + 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); + } + } - vc_progress_count++; - if( vc_progress_count >= vc_progress->count) - vc_progress_count = 0; + if ((x + width) > (int)vinfo.v_width) break; + if ((y + height) > (int)vinfo.v_height) break; - width = vc_progress->width; - height = vc_progress->height; - x = vc_progress->dx; - y = vc_progress->dy; - data = vc_progress_data; data += vc_progress_count * width * height; - if( 1 & vc_progress->flags) { - x += ((vinfo.v_width - width) / 2); - y += ((vinfo.v_height - height) / 2); - } - vc_blit_rect( x, y, 0, + + vc_blit_rect( x, y, 0, width, height, width, width, data, vc_saveunder, - kDataAlpha | (vc_needsave ? kSave : 0) ); - vc_needsave = FALSE; + 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); + 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); } @@ -2335,11 +2715,11 @@ vc_progress_task(__unused void *arg0, __unused void *arg) static boolean_t gc_acquired = FALSE; 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 ) @@ -2356,51 +2736,112 @@ gc_pause( boolean_t pause, boolean_t graphics_now ) simple_lock(&vc_progress_lock); - vc_progress_enable = gc_graphics_boot && !gc_desire_text && !pause; - if (vc_progress_enable) - thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline); + if (pause) + { + gc_paused_progress = vc_progress_enable; + vc_progress_enable = FALSE; + } + else vc_progress_enable = gc_paused_progress; + + if (vc_progress_enable) + { +#if !CONFIG_EMBEDDED + if (1 & vc_progress_withmeter) thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline); + else +#endif /* !CONFIG_EMBEDDED */ + thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline); + } simple_unlock(&vc_progress_lock); splx(s); } +static void +vc_initialize(__unused struct vc_info * vinfo_p) +{ +#ifdef __arm__ + unsigned long cnt, data16, data32; + + if (vinfo.v_depth == 16) { + for (cnt = 0; cnt < 8; cnt++) { + data32 = vc_colors[cnt][2]; + data16 = (data32 & 0x0000F8) << 8; + data16 |= (data32 & 0x00FC00) >> 5; + data16 |= (data32 & 0xF80000) >> 19; + data16 |= data16 << 16; + vc_colors[cnt][1] = data16; + } + } +#endif + + vinfo.v_rows = vinfo.v_height / ISO_CHAR_HEIGHT; + vinfo.v_columns = vinfo.v_width / ISO_CHAR_WIDTH; + vinfo.v_rowscanbytes = ((vinfo.v_depth + 7) / 8) * vinfo.v_width; + vc_uiscale = vinfo.v_scale; + if (vc_uiscale > kMaxProgressData) vc_uiscale = kMaxProgressData; + else if (!vc_uiscale) vc_uiscale = 1; +} + 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; + 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; + new_vinfo.v_type = (unsigned int)boot_vinfo->v_display; #else - new_vinfo.v_type = 0; + new_vinfo.v_type = 0; #endif + unsigned int scale = (unsigned int)boot_vinfo->v_scale; + if (scale == kPEScaleFactor1x ) + new_vinfo.v_scale = kPEScaleFactor1x; + else if (scale == kPEScaleFactor2x) + new_vinfo.v_scale = kPEScaleFactor2x; + else /* Scale factor not set, default to 1x */ + new_vinfo.v_scale = kPEScaleFactor1x; } - - 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) */ + new_vinfo.v_name[0] = 0; + new_vinfo.v_physaddr = 0; - if (!new_vinfo.v_physaddr) /* Check to see if we have a framebuffer */ + /* + * 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 (!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 */ @@ -2411,40 +2852,21 @@ 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) << 12) | (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) - new_vinfo.v_baseaddr |= VM_MIN_KERNEL_ADDRESS; + new_vinfo.v_baseaddr |= (VM_MIN_KERNEL_ADDRESS & ~LOW_4GB_MASK); #endif /* Update the vinfo structure atomically with respect to the vc_progress task if running */ @@ -2462,24 +2884,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? */ { -#if FALSE - if(lastVideoMapped) /* Was this not a special pre-VM mapping? */ -#endif + /* 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) @@ -2497,30 +2918,36 @@ initialize_screen(PE_Video * boot_vinfo, unsigned int op) gc_ops.update_color = vc_update_color; gc_initialize(&vinfo); } - -#ifdef GRATEFULDEBUGGER - GratefulDebInit((bootBumbleC *)boot_vinfo); /* Re-initialize GratefulDeb */ -#endif /* GRATEFULDEBUGGER */ } graphics_now = gc_graphics_boot && !gc_desire_text; switch ( op ) { case kPEGraphicsMode: - panicDialogDesired = TRUE; gc_graphics_boot = TRUE; gc_desire_text = FALSE; break; case kPETextMode: - panicDialogDesired = FALSE; - disable_debug_output = FALSE; gc_graphics_boot = FALSE; break; case kPEAcquireScreen: if ( gc_acquired ) break; - vc_progress_set( graphics_now, kProgressAcquireDelay ); + + 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; + +#if !defined(XNU_TARGET_OS_BRIDGE) + vc_progress_set( graphics_now, delay ); +#endif /* !defined(XNU_TARGET_OS_BRIDGE) */ gc_enable( !graphics_now ); gc_acquired = TRUE; gc_desire_text = FALSE; @@ -2543,8 +2970,6 @@ initialize_screen(PE_Video * boot_vinfo, unsigned int op) case kPETextScreen: if ( console_is_serial() ) break; - panicDialogDesired = FALSE; - disable_debug_output = FALSE; if ( gc_acquired == FALSE ) { gc_desire_text = TRUE; @@ -2563,52 +2988,45 @@ initialize_screen(PE_Video * boot_vinfo, unsigned int op) gc_acquired = FALSE; gc_desire_text = FALSE; gc_enable( FALSE ); + if ( gc_graphics_boot == FALSE ) break; + vc_progress_set( FALSE, 0 ); + vc_acquire_delay = kProgressReacquireDelay; + vc_progress_white = TRUE; #if !CONFIG_EMBEDDED - vc_enable_progressmeter( FALSE ); + vc_enable_progressmeter(FALSE); + vc_progress_withmeter &= ~1; #endif - vc_clut8 = NULL; -#ifdef GRATEFULDEBUGGER - GratefulDebInit(0); /* Stop grateful debugger */ -#endif /* GRATEFULDEBUGGER */ break; - } -#ifdef GRATEFULDEBUGGER - if ( boot_vinfo ) GratefulDebInit((bootBumbleC *)boot_vinfo); /* Re initialize GratefulDeb */ -#endif /* GRATEFULDEBUGGER */ -} -void -dim_screen(void) -{ - unsigned int *p, *endp, *row; - int col, rowline, rowlongs; - register unsigned int mask; - if(!vinfo.v_depth) - return; +#if !CONFIG_EMBEDDED + case kPERefreshBootGraphics: + { + spl_t s; + boolean_t save; - 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; + if (kBootArgsFlagBlack & ((boot_args *) PE_state.bootArgs)->flags) break; - rowline = (int)(vinfo.v_rowscanbytes / 4); - rowlongs = (int)(vinfo.v_rowbytes / 4); + save = vc_progress_white; + vc_progress_white = (0 != (kBootArgsFlagBlackBg & ((boot_args *) PE_state.bootArgs)->flags)); - p = (unsigned int*) vinfo.v_baseaddr; - endp = p + (rowlongs * vinfo.v_height); + internal_enable_progressmeter(kProgressMeterKernel); - for (row = p ; row < endp ; row += rowlongs) { - for (p = &row[0], col = 0; col < rowline; col++) { - *p = (*p >> 1) & mask; - ++p; + s = splhigh(); + simple_lock(&vc_progress_lock); + + vc_progressmeter_drawn = 0; + internal_set_progressmeter(vc_progressmeter_range(vc_progressmeter_count >> 13)); + + simple_unlock(&vc_progress_lock); + splx(s); + + internal_enable_progressmeter(kProgressMeterOff); + vc_progress_white = save; } +#endif } } @@ -2619,6 +3037,26 @@ vcattach(void) { vm_initialized = TRUE; +#if !CONFIG_EMBEDDED + const boot_args * bootargs = (typeof(bootargs)) PE_state.bootArgs; + + vc_progress_white = (0 != ((kBootArgsFlagBlackBg | kBootArgsFlagLoginUI) + & 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; + } +#endif + simple_lock_init(&vc_progress_lock, 0); + if ( gc_graphics_boot == FALSE ) { long index; @@ -2632,6 +3070,10 @@ vcattach(void) for ( index = 0 ; index < msgbufp->msg_bufx ; index++ ) { + if (msgbufp->msg_bufc[index] == '\0') { + continue; + } + vcputc( 0, 0, msgbufp->msg_bufc[index] ); if ( msgbufp->msg_bufc[index] == '\n' ) @@ -2644,100 +3086,124 @@ vcattach(void) #if !CONFIG_EMBEDDED -int vc_progress_meter_enable; -int vc_progress_meter_value; - -static void * vc_progress_meter_backbuffer; -static int vc_progress_meter_drawn; - +// redraw progress meter between pixels x1, x2, position at x3 static void -vc_draw_progress_meter(int select, unsigned int flags, int x1, int x2) +vc_draw_progress_meter(unsigned int flags, int x1, int x2, int x3) { const unsigned char * data; int x, w; int ox, oy; + int endCapPos; + int onoff; + // 1 rounded fill, 0 square end + int style = (0 == (2 & vc_progress_withmeter)); - ox = ((vinfo.v_width - kProgressBarWidth) / 2); - oy = vinfo.v_height - (((vinfo.v_height / 2) - vc_progress->dy + kProgressBarHeight) / 2); + ox = ((vinfo.v_width - (kProgressBarWidth * vc_uiscale)) / 2); + oy = vinfo.v_height - (vinfo.v_height / 3) - ((kProgressBarHeight * vc_uiscale) / 2); if (kDataBack == flags) { // restore back bits vc_blit_rect(ox + x1, oy, x1, - x2, kProgressBarHeight, 0, kProgressBarWidth, - NULL, vc_progress_meter_backbuffer, flags); + x2, (kProgressBarHeight * vc_uiscale), 0, (kProgressBarWidth * vc_uiscale), + NULL, vc_progressmeter_backbuffer, flags); return; } for (x = x1; x < x2; x += w) { - if (x < kProgressBarCapWidth) + onoff = (x < x3); + endCapPos = ((style && onoff) ? x3 : (kProgressBarWidth * vc_uiscale)); + if (x < (kProgressBarCapWidth * vc_uiscale)) { - if (x2 < kProgressBarCapWidth) + if (x2 < (kProgressBarCapWidth * vc_uiscale)) w = x2 - x; else - w = kProgressBarCapWidth - x; - data = &progressmeter_leftcap[select & 1][0]; + w = (kProgressBarCapWidth * vc_uiscale) - x; + data = progressmeter_leftcap[vc_uiscale >= 2][onoff]; data += x; - vc_blit_rect(ox + x, oy, x, - w, kProgressBarHeight, kProgressBarCapWidth, kProgressBarWidth, - data, vc_progress_meter_backbuffer, flags); + vc_blit_rect(ox + x, oy, x, w, + (kProgressBarHeight * vc_uiscale), + (kProgressBarCapWidth * vc_uiscale), + (kProgressBarWidth * vc_uiscale), + data, vc_progressmeter_backbuffer, flags); } - else if (x < (kProgressBarWidth - kProgressBarCapWidth)) + else if (x < (endCapPos - (kProgressBarCapWidth * vc_uiscale))) { - if (x2 < (kProgressBarWidth - kProgressBarCapWidth)) + if (x2 < (endCapPos - (kProgressBarCapWidth * vc_uiscale))) w = x2 - x; else - w = (kProgressBarWidth - kProgressBarCapWidth) - x; - data = &progressmeter_middle[select & 1][0]; - vc_blit_rect(ox + x, oy, x, - w, kProgressBarHeight, 1, kProgressBarWidth, - data, vc_progress_meter_backbuffer, flags); + w = (endCapPos - (kProgressBarCapWidth * vc_uiscale)) - x; + data = progressmeter_middle[vc_uiscale >= 2][onoff]; + vc_blit_rect(ox + x, oy, x, w, + (kProgressBarHeight * vc_uiscale), + 1, + (kProgressBarWidth * vc_uiscale), + data, vc_progressmeter_backbuffer, flags); } else { - w = x2 - x; - data = &progressmeter_rightcap[select & 1][0]; - data += x - (kProgressBarWidth - kProgressBarCapWidth); - vc_blit_rect(ox + x, oy, x, - w, kProgressBarHeight, kProgressBarCapWidth, kProgressBarWidth, - data, vc_progress_meter_backbuffer, flags); + w = endCapPos - x; + data = progressmeter_rightcap[vc_uiscale >= 2][onoff]; + data += x - (endCapPos - (kProgressBarCapWidth * vc_uiscale)); + vc_blit_rect(ox + x, oy, x, w, + (kProgressBarHeight * vc_uiscale), + (kProgressBarCapWidth * vc_uiscale), + (kProgressBarWidth * vc_uiscale), + data, vc_progressmeter_backbuffer, flags); } } } -void -vc_enable_progressmeter(int new_value) +extern void IORecordProgressBackbuffer(void * buffer, size_t size, uint32_t theme); + +static void +internal_enable_progressmeter(int new_value) { - spl_t s; - void * new_buffer = NULL; + spl_t s; + void * new_buffer; + boolean_t stashBackbuffer; + stashBackbuffer = FALSE; + new_buffer = NULL; if (new_value) - new_buffer = kalloc(kProgressBarWidth * kProgressBarHeight * sizeof(int)); + { + new_buffer = kalloc((kProgressBarWidth * vc_uiscale) + * (kProgressBarHeight * vc_uiscale) * sizeof(int)); + } s = splhigh(); simple_lock(&vc_progress_lock); - if (gc_enabled || !gc_acquired || !gc_graphics_boot) - new_value = FALSE; + if (kProgressMeterUser == new_value) + { + if (gc_enabled || !gc_acquired || !gc_graphics_boot + || (kProgressMeterKernel == vc_progressmeter_enable)) new_value = vc_progressmeter_enable; + } - if (new_value != vc_progress_meter_enable) + if (new_value != vc_progressmeter_enable) { if (new_value) { - vc_progress_meter_backbuffer = new_buffer; - vc_draw_progress_meter(FALSE, kDataAlpha | kSave, 0, kProgressBarWidth); - vc_progress_meter_enable = TRUE; - new_buffer = NULL; - vc_progress_meter_drawn = 0; + if (kProgressMeterOff == vc_progressmeter_enable) + { + vc_progressmeter_backbuffer = new_buffer; + vc_draw_progress_meter(kDataAlpha | kSave, 0, (kProgressBarWidth * vc_uiscale), 0); + new_buffer = NULL; + vc_progressmeter_drawn = 0; + } + vc_progressmeter_enable = new_value; } - else if (vc_progress_meter_backbuffer) + else if (vc_progressmeter_backbuffer) { - vc_draw_progress_meter(0, kDataBack, 0, kProgressBarWidth); - new_buffer = vc_progress_meter_backbuffer; - vc_progress_meter_backbuffer = NULL; - vc_progress_meter_enable = FALSE; - + if (kProgressMeterUser == vc_progressmeter_enable) + { + vc_draw_progress_meter(kDataBack, 0, (kProgressBarWidth * vc_uiscale), vc_progressmeter_drawn); + } + else stashBackbuffer = TRUE; + new_buffer = vc_progressmeter_backbuffer; + vc_progressmeter_backbuffer = NULL; + vc_progressmeter_enable = FALSE; } } @@ -2745,35 +3211,80 @@ vc_enable_progressmeter(int new_value) splx(s); if (new_buffer) - kfree(new_buffer, kProgressBarWidth * kProgressBarHeight * sizeof(int)); + { + if (stashBackbuffer) IORecordProgressBackbuffer(new_buffer, + (kProgressBarWidth * vc_uiscale) + * (kProgressBarHeight * vc_uiscale) + * sizeof(int), + vc_progress_white); + kfree(new_buffer, (kProgressBarWidth * vc_uiscale) + * (kProgressBarHeight * vc_uiscale) * sizeof(int)); + } +} + +static void +internal_set_progressmeter(int new_value) +{ + int x1, x3; + int capRedraw; + // 1 rounded fill, 0 square end + int style = (0 == (2 & vc_progress_withmeter)); + + if ((new_value < 0) || (new_value > kProgressMeterMax)) return; + + if (vc_progressmeter_enable) + { + vc_progressmeter_value = new_value; + + capRedraw = (style ? (kProgressBarCapWidth * vc_uiscale) : 0); + x3 = (((kProgressBarWidth * vc_uiscale) - 2 * capRedraw) * vc_progressmeter_value) / kProgressMeterMax; + x3 += (2 * capRedraw); + + if (x3 > vc_progressmeter_drawn) + { + x1 = capRedraw; + if (x1 > vc_progressmeter_drawn) x1 = vc_progressmeter_drawn; + vc_draw_progress_meter(kDataAlpha, vc_progressmeter_drawn - x1, x3, x3); + } + else + { + vc_draw_progress_meter(kDataAlpha, x3 - capRedraw, vc_progressmeter_drawn, x3); + } + vc_progressmeter_drawn = x3; + } +} + +void +vc_enable_progressmeter(int new_value) +{ + if (kProgressMeterKernel == vc_progressmeter_enable) + { + vc_progressmeter_hold = new_value; + } + else + { + internal_enable_progressmeter(new_value ? kProgressMeterUser : kProgressMeterOff); + } } void vc_set_progressmeter(int new_value) { spl_t s; - int x2; - - if ((new_value < 0) | (new_value > 100)) - return; s = splhigh(); simple_lock(&vc_progress_lock); - if (vc_progress_meter_enable) + if (vc_progressmeter_enable && (kProgressMeterKernel != vc_progressmeter_enable)) { - vc_progress_meter_value = new_value; - x2 = ((kProgressBarWidth - 1) * new_value) / 100; - if (x2 > vc_progress_meter_drawn) - vc_draw_progress_meter(TRUE, kDataAlpha, vc_progress_meter_drawn, x2); - else - vc_draw_progress_meter(FALSE, kDataAlpha, x2, vc_progress_meter_drawn); - vc_progress_meter_drawn = x2; + internal_set_progressmeter((new_value * kProgressMeterMax) / 100); } - + simple_unlock(&vc_progress_lock); splx(s); } #endif /* !CONFIG_EMBEDDED */ + +