@@ -133,13 +133,11 @@ void efi_parse_option_graphics(char *option)
133133
134134static u32 choose_mode_modenum (efi_graphics_output_protocol_t * gop )
135135{
136- efi_status_t status ;
137-
136+ efi_graphics_output_mode_info_t * info __free (efi_pool ) = NULL ;
138137 efi_graphics_output_protocol_mode_t * mode ;
139- efi_graphics_output_mode_info_t * info ;
140138 unsigned long info_size ;
141-
142139 u32 max_mode , cur_mode ;
140+ efi_status_t status ;
143141 int pf ;
144142
145143 mode = efi_table_attr (gop , mode );
@@ -154,17 +152,13 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
154152 return cur_mode ;
155153 }
156154
157- status = efi_call_proto (gop , query_mode , cmdline .mode ,
158- & info_size , & info );
155+ status = efi_call_proto (gop , query_mode , cmdline .mode , & info_size , & info );
159156 if (status != EFI_SUCCESS ) {
160157 efi_err ("Couldn't get mode information\n" );
161158 return cur_mode ;
162159 }
163160
164161 pf = info -> pixel_format ;
165-
166- efi_bs_call (free_pool , info );
167-
168162 if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX ) {
169163 efi_err ("Invalid PixelFormat\n" );
170164 return cur_mode ;
@@ -173,6 +167,28 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
173167 return cmdline .mode ;
174168}
175169
170+ static u32 choose_mode (efi_graphics_output_protocol_t * gop ,
171+ bool (* match )(const efi_graphics_output_mode_info_t * , u32 , void * ),
172+ void * ctx )
173+ {
174+ efi_graphics_output_protocol_mode_t * mode = efi_table_attr (gop , mode );
175+ u32 max_mode = efi_table_attr (mode , max_mode );
176+
177+ for (u32 m = 0 ; m < max_mode ; m ++ ) {
178+ efi_graphics_output_mode_info_t * info __free (efi_pool ) = NULL ;
179+ unsigned long info_size ;
180+ efi_status_t status ;
181+
182+ status = efi_call_proto (gop , query_mode , m , & info_size , & info );
183+ if (status != EFI_SUCCESS )
184+ continue ;
185+
186+ if (match (info , m , ctx ))
187+ return m ;
188+ }
189+ return (unsigned long )ctx ;
190+ }
191+
176192static u8 pixel_bpp (int pixel_format , efi_pixel_bitmask_t pixel_info )
177193{
178194 if (pixel_format == PIXEL_BIT_MASK ) {
@@ -185,192 +201,117 @@ static u8 pixel_bpp(int pixel_format, efi_pixel_bitmask_t pixel_info)
185201 return 32 ;
186202}
187203
188- static u32 choose_mode_res ( efi_graphics_output_protocol_t * gop )
204+ static bool match_res ( const efi_graphics_output_mode_info_t * info , u32 mode , void * ctx )
189205{
190- efi_status_t status ;
206+ efi_pixel_bitmask_t pi = info -> pixel_information ;
207+ int pf = info -> pixel_format ;
191208
192- efi_graphics_output_protocol_mode_t * mode ;
193- efi_graphics_output_mode_info_t * info ;
194- unsigned long info_size ;
195-
196- u32 max_mode , cur_mode ;
197- int pf ;
198- efi_pixel_bitmask_t pi ;
199- u32 m , w , h ;
209+ if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX )
210+ return false;
200211
201- mode = efi_table_attr (gop , mode );
212+ return cmdline .res .width == info -> horizontal_resolution &&
213+ cmdline .res .height == info -> vertical_resolution &&
214+ (cmdline .res .format < 0 || cmdline .res .format == pf ) &&
215+ (!cmdline .res .depth || cmdline .res .depth == pixel_bpp (pf , pi ));
216+ }
202217
203- cur_mode = efi_table_attr (mode , mode );
204- info = efi_table_attr (mode , info );
205- pf = info -> pixel_format ;
206- pi = info -> pixel_information ;
207- w = info -> horizontal_resolution ;
208- h = info -> vertical_resolution ;
218+ static u32 choose_mode_res (efi_graphics_output_protocol_t * gop )
219+ {
220+ efi_graphics_output_protocol_mode_t * mode = efi_table_attr (gop , mode );
221+ unsigned long cur_mode = efi_table_attr (mode , mode );
209222
210- if (w == cmdline .res .width && h == cmdline .res .height &&
211- (cmdline .res .format < 0 || cmdline .res .format == pf ) &&
212- (!cmdline .res .depth || cmdline .res .depth == pixel_bpp (pf , pi )))
223+ if (match_res (efi_table_attr (mode , info ), cur_mode , NULL ))
213224 return cur_mode ;
214225
215- max_mode = efi_table_attr (mode , max_mode );
216-
217- for (m = 0 ; m < max_mode ; m ++ ) {
218- if (m == cur_mode )
219- continue ;
220-
221- status = efi_call_proto (gop , query_mode , m ,
222- & info_size , & info );
223- if (status != EFI_SUCCESS )
224- continue ;
226+ return choose_mode (gop , match_res , (void * )cur_mode );
227+ }
225228
226- pf = info -> pixel_format ;
227- pi = info -> pixel_information ;
228- w = info -> horizontal_resolution ;
229- h = info -> vertical_resolution ;
229+ struct match {
230+ u32 mode ;
231+ u32 area ;
232+ u8 depth ;
233+ };
230234
231- efi_bs_call (free_pool , info );
235+ static bool match_auto (const efi_graphics_output_mode_info_t * info , u32 mode , void * ctx )
236+ {
237+ u32 area = info -> horizontal_resolution * info -> vertical_resolution ;
238+ efi_pixel_bitmask_t pi = info -> pixel_information ;
239+ int pf = info -> pixel_format ;
240+ u8 depth = pixel_bpp (pf , pi );
241+ struct match * m = ctx ;
232242
233- if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX )
234- continue ;
235- if (w == cmdline .res .width && h == cmdline .res .height &&
236- (cmdline .res .format < 0 || cmdline .res .format == pf ) &&
237- (!cmdline .res .depth || cmdline .res .depth == pixel_bpp (pf , pi )))
238- return m ;
239- }
243+ if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX )
244+ return false;
240245
241- efi_err ("Couldn't find requested mode\n" );
246+ if (area > m -> area || (area == m -> area && depth > m -> depth ))
247+ * m = (struct match ){ mode , area , depth };
242248
243- return cur_mode ;
249+ return false ;
244250}
245251
246252static u32 choose_mode_auto (efi_graphics_output_protocol_t * gop )
247253{
248- efi_status_t status ;
254+ struct match match = {} ;
249255
250- efi_graphics_output_protocol_mode_t * mode ;
251- efi_graphics_output_mode_info_t * info ;
252- unsigned long info_size ;
256+ choose_mode (gop , match_auto , & match );
253257
254- u32 max_mode , cur_mode , best_mode , area ;
255- u8 depth ;
256- int pf ;
257- efi_pixel_bitmask_t pi ;
258- u32 m , w , h , a ;
259- u8 d ;
260-
261- mode = efi_table_attr (gop , mode );
262-
263- cur_mode = efi_table_attr (mode , mode );
264- max_mode = efi_table_attr (mode , max_mode );
265-
266- info = efi_table_attr (mode , info );
267-
268- pf = info -> pixel_format ;
269- pi = info -> pixel_information ;
270- w = info -> horizontal_resolution ;
271- h = info -> vertical_resolution ;
272-
273- best_mode = cur_mode ;
274- area = w * h ;
275- depth = pixel_bpp (pf , pi );
276-
277- for (m = 0 ; m < max_mode ; m ++ ) {
278- if (m == cur_mode )
279- continue ;
280-
281- status = efi_call_proto (gop , query_mode , m ,
282- & info_size , & info );
283- if (status != EFI_SUCCESS )
284- continue ;
258+ return match .mode ;
259+ }
285260
286- pf = info -> pixel_format ;
287- pi = info -> pixel_information ;
288- w = info -> horizontal_resolution ;
289- h = info -> vertical_resolution ;
261+ static bool match_list (const efi_graphics_output_mode_info_t * info , u32 mode , void * ctx )
262+ {
263+ efi_pixel_bitmask_t pi = info -> pixel_information ;
264+ u32 cur_mode = (unsigned long )ctx ;
265+ int pf = info -> pixel_format ;
266+ const char * dstr ;
267+ u8 depth = 0 ;
268+ bool valid ;
290269
291- efi_bs_call ( free_pool , info );
270+ valid = !( pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX );
292271
293- if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX )
294- continue ;
295- a = w * h ;
296- if (a < area )
297- continue ;
298- d = pixel_bpp (pf , pi );
299- if (a > area || d > depth ) {
300- best_mode = m ;
301- area = a ;
302- depth = d ;
303- }
272+ switch (pf ) {
273+ case PIXEL_RGB_RESERVED_8BIT_PER_COLOR :
274+ dstr = "rgb" ;
275+ break ;
276+ case PIXEL_BGR_RESERVED_8BIT_PER_COLOR :
277+ dstr = "bgr" ;
278+ break ;
279+ case PIXEL_BIT_MASK :
280+ dstr = "" ;
281+ depth = pixel_bpp (pf , pi );
282+ break ;
283+ case PIXEL_BLT_ONLY :
284+ dstr = "blt" ;
285+ break ;
286+ default :
287+ dstr = "xxx" ;
288+ break ;
304289 }
305290
306- return best_mode ;
291+ efi_printk ("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n" ,
292+ mode ,
293+ (mode == cur_mode ) ? '*' : ' ' ,
294+ !valid ? '-' : ' ' ,
295+ info -> horizontal_resolution ,
296+ info -> vertical_resolution ,
297+ dstr , depth );
298+
299+ return false;
307300}
308301
309302static u32 choose_mode_list (efi_graphics_output_protocol_t * gop )
310303{
311- efi_status_t status ;
312-
313- efi_graphics_output_protocol_mode_t * mode ;
314- efi_graphics_output_mode_info_t * info ;
315- unsigned long info_size ;
316-
317- u32 max_mode , cur_mode ;
318- int pf ;
319- efi_pixel_bitmask_t pi ;
320- u32 m , w , h ;
321- u8 d ;
322- const char * dstr ;
323- bool valid ;
304+ efi_graphics_output_protocol_mode_t * mode = efi_table_attr (gop , mode );
305+ unsigned long cur_mode = efi_table_attr (mode , mode );
306+ u32 max_mode = efi_table_attr (mode , max_mode );
324307 efi_input_key_t key ;
325-
326- mode = efi_table_attr (gop , mode );
327-
328- cur_mode = efi_table_attr (mode , mode );
329- max_mode = efi_table_attr (mode , max_mode );
308+ efi_status_t status ;
330309
331310 efi_printk ("Available graphics modes are 0-%u\n" , max_mode - 1 );
332311 efi_puts (" * = current mode\n"
333312 " - = unusable mode\n" );
334- for (m = 0 ; m < max_mode ; m ++ ) {
335- status = efi_call_proto (gop , query_mode , m ,
336- & info_size , & info );
337- if (status != EFI_SUCCESS )
338- continue ;
339313
340- pf = info -> pixel_format ;
341- pi = info -> pixel_information ;
342- w = info -> horizontal_resolution ;
343- h = info -> vertical_resolution ;
344-
345- efi_bs_call (free_pool , info );
346-
347- valid = !(pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX );
348- d = 0 ;
349- switch (pf ) {
350- case PIXEL_RGB_RESERVED_8BIT_PER_COLOR :
351- dstr = "rgb" ;
352- break ;
353- case PIXEL_BGR_RESERVED_8BIT_PER_COLOR :
354- dstr = "bgr" ;
355- break ;
356- case PIXEL_BIT_MASK :
357- dstr = "" ;
358- d = pixel_bpp (pf , pi );
359- break ;
360- case PIXEL_BLT_ONLY :
361- dstr = "blt" ;
362- break ;
363- default :
364- dstr = "xxx" ;
365- break ;
366- }
367-
368- efi_printk ("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n" ,
369- m ,
370- m == cur_mode ? '*' : ' ' ,
371- !valid ? '-' : ' ' ,
372- w , h , dstr , d );
373- }
314+ choose_mode (gop , match_list , (void * )cur_mode );
374315
375316 efi_puts ("\nPress any key to continue (or wait 10 seconds)\n" );
376317 status = efi_wait_for_key (10 * EFI_USEC_PER_SEC , & key );
0 commit comments