@@ -92,19 +92,29 @@ static void fb_set_logo_truepalette(struct fb_info *info,
9292 }
9393}
9494
95- static void fb_set_logo_RGB_palette (struct image_palette * palette ,
96- u32 * palette_to_write , int current_rows )
95+ static void fb_set_logo_RGB_palette (struct fb_info * info ,
96+ struct image_palette * pal_in ,
97+ u32 * pal_out , int current_rows )
9798{
9899 // Set the kernel palette from an array of RGB values
99- uint32_t color_code ;
100+ static const unsigned char mask [] = {
101+ 0 , 0x80 , 0xc0 , 0xe0 , 0xf0 , 0xf8 , 0xfc , 0xfe , 0xff
102+ };
103+ unsigned char redmask , greenmask , bluemask ;
104+ int redshift , greenshift , blueshift ;
100105 int i ;
101106
102- // Color format is RGB565, remove LSB 3 bits, and move to correct position
107+ redmask = mask [info -> var .red .length < 8 ? info -> var .red .length : 8 ];
108+ greenmask = mask [info -> var .green .length < 8 ? info -> var .green .length : 8 ];
109+ bluemask = mask [info -> var .blue .length < 8 ? info -> var .blue .length : 8 ];
110+ redshift = info -> var .red .offset - (8 - info -> var .red .length );
111+ greenshift = info -> var .green .offset - (8 - info -> var .green .length );
112+ blueshift = info -> var .blue .offset - (8 - info -> var .blue .length );
113+
103114 for (i = 0 ; i < current_rows ; i ++ ) {
104- color_code = ((((uint16_t )palette -> colors [i ][0 ]) >> 3 ) << 11 ) |
105- ((((uint16_t )palette -> colors [i ][1 ]) >> 2 ) << 5 ) |
106- (((uint16_t )palette -> colors [i ][2 ]) >> 3 );
107- palette_to_write [i + 32 ] = color_code ;
115+ pal_out [i + 32 ] = (safe_shift ((pal_in -> colors [i ][0 ] & redmask ), redshift ) |
116+ safe_shift ((pal_in -> colors [i ][1 ] & greenmask ), greenshift ) |
117+ safe_shift ((pal_in -> colors [i ][2 ] & bluemask ), blueshift ));
108118 }
109119}
110120
@@ -339,8 +349,8 @@ static void fb_set_logo_from_file(struct fb_info *info, const char *filepath,
339349{
340350 int current_rows = 0 , palette_index = 0 , actual_row , skip_x = 0 , skip_y = 0 , ret ;
341351 unsigned char * read_logo = NULL , * header ;
342- const char * file_content = NULL ;
343- const struct firmware * fw ;
352+ const char * file_content ;
353+ const struct firmware * fw = NULL ;
344354 struct image_palette image_palette ;
345355 const char * current_ptr , * end_ptr ;
346356 long width = 0 , height = 0 ;
@@ -349,98 +359,108 @@ static void fb_set_logo_from_file(struct fb_info *info, const char *filepath,
349359 u8 entry [3 ];
350360 ssize_t len ;
351361
352- ret = request_firmware (& fw , filepath , info -> device );
362+ ret = firmware_request_nowarn (& fw , filepath , info -> device );
353363 if (ret ) {
354364 pr_info ("Failed to load logo file '%s': %d\n" , filepath , ret );
355365 goto cleanup ;
356366 }
357367 len = fw -> size ;
358368 file_content = fw -> data ;
359369
360- if (len > 0 ) {
361- current_ptr = file_content ;
362- end_ptr = file_content + len ;
363- if (len < 18 ) {
364- pr_err ("Invalid logo file: TGA file too small for header\n" );
365- goto cleanup ;
366- }
367- header = (unsigned char * )file_content ;
368-
369- // Skip color map info (bytes 3-7)
370- // Skip image origin (bytes 8-11)
371- width = header [12 ] | (header [13 ] << 8 );
372- height = header [14 ] | (header [15 ] << 8 );
373-
374- // Only supports uncompressed true-color images (type 2) with 24-bit depth
375- if (header [2 ] != 2 || header [16 ] != 24 ) {
376- pr_err ("Unsupported TGA logo format: Type=%d, Depth=%d (only support Type=2, Depth=24)\n" ,
377- header [2 ], header [16 ]);
378- goto cleanup ;
379- }
380- // Skip header + ID field
381- current_ptr = file_content + 18 + header [0 ];
370+ if (!len ) {
371+ pr_err ("Error: logo TGA file is empty. Not drawing fullscreen logo.\n" );
372+ goto cleanup ;
373+ }
374+
375+ current_ptr = file_content ;
376+ end_ptr = file_content + len ;
377+ if (len < 18 ) {
378+ pr_err ("Invalid logo file: TGA file too small for header\n" );
379+ goto cleanup ;
380+ }
381+ header = (unsigned char * )file_content ;
382382
383- read_logo = kmalloc_array (width , height , GFP_KERNEL );
384- if (!read_logo )
385- goto cleanup ;
383+ // Skip color map info (bytes 3-7)
384+ // Skip image origin (bytes 8-11)
385+ width = header [12 ] | (header [13 ] << 8 );
386+ height = header [14 ] | (header [15 ] << 8 );
386387
387- image -> data = read_logo ;
388+ // Only supports uncompressed true-color images (type 2) with 24-bit depth
389+ if (header [2 ] != 2 || header [16 ] != 24 ) {
390+ pr_err ("Unsupported TGA logo format: Type=%d, Depth=%d (only support Type=2, Depth=24)\n" ,
391+ header [2 ], header [16 ]);
392+ goto cleanup ;
393+ }
394+ // Skip header + ID field
395+ current_ptr = file_content + 18 + header [0 ];
388396
389- // TGA pixels are stored bottom-to-top by default, unless bit 5 of
390- // image_descriptor is set
391- top_to_bottom = (header [17 ] & 0x20 ) != 0 ;
392- skip_x = 0 ;
393- skip_y = 0 ;
397+ read_logo = kmalloc_array (width , height , GFP_KERNEL );
398+ if (!read_logo )
399+ goto cleanup ;
394400
395- if (image -> width > info -> var .xres ) {
396- pr_info ("Logo is larger than screen, clipping horizontally" );
397- skip_x = (image -> width - info -> var .xres ) / 2 ;
398- }
399- if (image -> height > info -> var .yres ) {
400- pr_info ("Logo is larger than screen, clipping vertically" );
401- skip_y = (image -> height - info -> var .yres ) / 2 ;
402- }
403- current_ptr += skip_y * width * 3 + skip_x * 3 ;
404- // Parse pixel data (BGR format in TGA)
405- for (int i = 0 ; i < height - 2 * skip_y ; i ++ ) {
406- for (int j = 0 ; j < width - 2 * skip_x ; j ++ ) {
407- if (current_ptr + 3 > end_ptr ) {
408- pr_info ("TGA: Unexpected end of file\n" );
409- goto cleanup ;
410- }
411- B = (unsigned char )* current_ptr ++ ;
412- G = (unsigned char )* current_ptr ++ ;
413- R = (unsigned char )* current_ptr ++ ;
414- entry [0 ] = R ;
415- entry [1 ] = G ;
416- entry [2 ] = B ;
417- palette_index = 0 ;
418-
419- if (!fb_palette_contains_entry (& image_palette , current_rows ,
420- entry , 3 , & palette_index )) {
401+ image -> data = read_logo ;
402+
403+ // TGA pixels are stored bottom-to-top by default, unless bit 5 of
404+ // image_descriptor is set
405+ top_to_bottom = (header [17 ] & 0x20 ) != 0 ;
406+ skip_x = 0 ;
407+ skip_y = 0 ;
408+
409+ if (width > info -> var .xres ) {
410+ pr_info ("Logo is larger than screen (%lu vs %u), clipping horizontally\n" ,
411+ width , info -> var .xres );
412+ skip_x = (width - info -> var .xres ) / 2 ;
413+ }
414+ if (height > info -> var .yres ) {
415+ pr_info ("Logo is larger than screen (%lu vs %u), clipping vertically\n" ,
416+ height , info -> var .yres );
417+ skip_y = (height - info -> var .yres ) / 2 ;
418+ }
419+ current_ptr += skip_y * width * 3 + skip_x * 3 ;
420+ // Parse pixel data (BGR format in TGA)
421+ for (int i = 0 ; i < height - 2 * skip_y ; i ++ ) {
422+ for (int j = 0 ; j < width - 2 * skip_x ; j ++ ) {
423+ if (current_ptr + 3 > end_ptr ) {
424+ pr_info ("TGA: Unexpected end of file\n" );
425+ goto cleanup ;
426+ }
427+ B = (unsigned char )* current_ptr ++ ;
428+ G = (unsigned char )* current_ptr ++ ;
429+ R = (unsigned char )* current_ptr ++ ;
430+ entry [0 ] = R ;
431+ entry [1 ] = G ;
432+ entry [2 ] = B ;
433+ palette_index = 0 ;
434+
435+ if (!fb_palette_contains_entry (& image_palette , current_rows ,
436+ entry , 3 , & palette_index )) {
437+ if (current_rows < 224 ) {
421438 for (int k = 0 ; k < 3 ; k ++ )
422- image_palette .colors [current_rows ][k ] = entry [k ];
439+ image_palette .colors [current_rows ][k ] =
440+ entry [k ];
423441 palette_index = current_rows ;
424- current_rows ++ ;
425442 }
426- actual_row = top_to_bottom ? i : (height - 1 - i );
427-
428- read_logo [actual_row * (width - 2 * skip_x ) + j ] =
429- palette_index + 32 ;
443+ current_rows ++ ;
430444 }
431- current_ptr += skip_x * 3 * 2 ;
445+ actual_row = top_to_bottom ? i : (height - 1 - i );
446+
447+ read_logo [actual_row * (width - 2 * skip_x ) + j ] =
448+ palette_index + 32 ;
432449 }
450+ current_ptr += skip_x * 3 * 2 ;
451+ }
433452
434- // Set logo palette
435- palette = kmalloc (256 * 4 , GFP_KERNEL );
436- if (palette == NULL )
437- goto cleanup ;
438- fb_set_logo_RGB_palette (& image_palette , palette , current_rows );
439- info -> pseudo_palette = palette ;
453+ if (current_rows >= 224 )
454+ pr_err ("Palette overflow. Entries clipped\n" );
440455
441- } else {
442- pr_err ("Error: logo TGA file is empty. Not drawing fullscreen logo.\n" );
443- }
456+ // Set logo palette
457+ palette = kzalloc (256 * 4 , GFP_KERNEL );
458+ if (!palette )
459+ goto cleanup ;
460+ fb_set_logo_RGB_palette (info , & image_palette , palette , current_rows );
461+ if (info -> pseudo_palette )
462+ memcpy (palette , info -> pseudo_palette , 32 * sizeof (uint32_t ));
463+ info -> pseudo_palette = palette ;
444464
445465 image -> width = min_t (unsigned int , width , info -> var .xres );
446466 image -> height = min_t (unsigned int , height , info -> var .yres );
@@ -455,8 +475,7 @@ static void fb_set_logo_from_file(struct fb_info *info, const char *filepath,
455475
456476cleanup :
457477 kfree (read_logo );
458- if (file_content )
459- kvfree (file_content );
478+ release_firmware (fw );
460479}
461480
462481
0 commit comments