6
6
* ----------------------------------------------------------------------- */
7
7
8
8
#include <linux/bitops.h>
9
+ #include <linux/ctype.h>
9
10
#include <linux/efi.h>
10
11
#include <linux/screen_info.h>
11
12
#include <linux/string.h>
17
18
enum efi_cmdline_option {
18
19
EFI_CMDLINE_NONE ,
19
20
EFI_CMDLINE_MODE_NUM ,
21
+ EFI_CMDLINE_RES
20
22
};
21
23
22
24
static struct {
23
25
enum efi_cmdline_option option ;
24
- u32 mode ;
26
+ union {
27
+ u32 mode ;
28
+ struct {
29
+ u32 width , height ;
30
+ } res ;
31
+ };
25
32
} cmdline __efistub_global = { .option = EFI_CMDLINE_NONE };
26
33
27
34
static bool parse_modenum (char * option , char * * next )
@@ -41,11 +48,33 @@ static bool parse_modenum(char *option, char **next)
41
48
return true;
42
49
}
43
50
51
+ static bool parse_res (char * option , char * * next )
52
+ {
53
+ u32 w , h ;
54
+
55
+ if (!isdigit (* option ))
56
+ return false;
57
+ w = simple_strtoull (option , & option , 10 );
58
+ if (* option ++ != 'x' || !isdigit (* option ))
59
+ return false;
60
+ h = simple_strtoull (option , & option , 10 );
61
+ if (* option && * option ++ != ',' )
62
+ return false;
63
+ cmdline .option = EFI_CMDLINE_RES ;
64
+ cmdline .res .width = w ;
65
+ cmdline .res .height = h ;
66
+
67
+ * next = option ;
68
+ return true;
69
+ }
70
+
44
71
void efi_parse_option_graphics (char * option )
45
72
{
46
73
while (* option ) {
47
74
if (parse_modenum (option , & option ))
48
75
continue ;
76
+ if (parse_res (option , & option ))
77
+ continue ;
49
78
50
79
while (* option && * option ++ != ',' )
51
80
;
@@ -94,6 +123,56 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
94
123
return cmdline .mode ;
95
124
}
96
125
126
+ static u32 choose_mode_res (efi_graphics_output_protocol_t * gop )
127
+ {
128
+ efi_status_t status ;
129
+
130
+ efi_graphics_output_protocol_mode_t * mode ;
131
+ efi_graphics_output_mode_info_t * info ;
132
+ unsigned long info_size ;
133
+
134
+ u32 max_mode , cur_mode ;
135
+ int pf ;
136
+ u32 m , w , h ;
137
+
138
+ mode = efi_table_attr (gop , mode );
139
+
140
+ cur_mode = efi_table_attr (mode , mode );
141
+ info = efi_table_attr (mode , info );
142
+ w = info -> horizontal_resolution ;
143
+ h = info -> vertical_resolution ;
144
+
145
+ if (w == cmdline .res .width && h == cmdline .res .height )
146
+ return cur_mode ;
147
+
148
+ max_mode = efi_table_attr (mode , max_mode );
149
+
150
+ for (m = 0 ; m < max_mode ; m ++ ) {
151
+ if (m == cur_mode )
152
+ continue ;
153
+
154
+ status = efi_call_proto (gop , query_mode , m ,
155
+ & info_size , & info );
156
+ if (status != EFI_SUCCESS )
157
+ continue ;
158
+
159
+ pf = info -> pixel_format ;
160
+ w = info -> horizontal_resolution ;
161
+ h = info -> vertical_resolution ;
162
+
163
+ efi_bs_call (free_pool , info );
164
+
165
+ if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX )
166
+ continue ;
167
+ if (w == cmdline .res .width && h == cmdline .res .height )
168
+ return m ;
169
+ }
170
+
171
+ efi_printk ("Couldn't find requested mode\n" );
172
+
173
+ return cur_mode ;
174
+ }
175
+
97
176
static void set_mode (efi_graphics_output_protocol_t * gop )
98
177
{
99
178
efi_graphics_output_protocol_mode_t * mode ;
@@ -103,6 +182,9 @@ static void set_mode(efi_graphics_output_protocol_t *gop)
103
182
case EFI_CMDLINE_MODE_NUM :
104
183
new_mode = choose_mode_modenum (gop );
105
184
break ;
185
+ case EFI_CMDLINE_RES :
186
+ new_mode = choose_mode_res (gop );
187
+ break ;
106
188
default :
107
189
return ;
108
190
}
0 commit comments