aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/boot
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/boot')
-rw-r--r--arch/x86/boot/Makefile2
-rw-r--r--arch/x86/boot/boot.h13
-rw-r--r--arch/x86/boot/compressed/eboot.c1017
-rw-r--r--arch/x86/boot/compressed/eboot.h60
-rw-r--r--arch/x86/boot/compressed/efi_stub_64.S29
-rw-r--r--arch/x86/boot/compressed/head_32.S52
-rw-r--r--arch/x86/boot/compressed/head_64.S111
-rw-r--r--arch/x86/boot/compressed/misc.c51
-rw-r--r--arch/x86/boot/compressed/string.c46
-rw-r--r--arch/x86/boot/cpucheck.c21
-rw-r--r--arch/x86/boot/edd.c1
-rw-r--r--arch/x86/boot/header.S25
-rw-r--r--arch/x86/boot/main.c1
-rw-r--r--arch/x86/boot/regs.c1
-rw-r--r--arch/x86/boot/string.c14
-rw-r--r--arch/x86/boot/string.h21
-rw-r--r--arch/x86/boot/tools/build.c77
-rw-r--r--arch/x86/boot/video-vesa.c1
18 files changed, 1220 insertions, 323 deletions
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 878df7e88cd4..abb9eba61b50 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -80,7 +80,7 @@ targets += voffset.h
80$(obj)/voffset.h: vmlinux FORCE 80$(obj)/voffset.h: vmlinux FORCE
81 $(call if_changed,voffset) 81 $(call if_changed,voffset)
82 82
83sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|startup_64\|efi_pe_entry\|efi_stub_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p' 83sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
84 84
85quiet_cmd_zoffset = ZOFFSET $@ 85quiet_cmd_zoffset = ZOFFSET $@
86 cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@ 86 cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index 50f8c5e0f37e..bd49ec61255c 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -177,14 +177,6 @@ static inline void wrgs32(u32 v, addr_t addr)
177} 177}
178 178
179/* Note: these only return true/false, not a signed return value! */ 179/* Note: these only return true/false, not a signed return value! */
180static inline int memcmp(const void *s1, const void *s2, size_t len)
181{
182 u8 diff;
183 asm("repe; cmpsb; setnz %0"
184 : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
185 return diff;
186}
187
188static inline int memcmp_fs(const void *s1, addr_t s2, size_t len) 180static inline int memcmp_fs(const void *s1, addr_t s2, size_t len)
189{ 181{
190 u8 diff; 182 u8 diff;
@@ -228,11 +220,6 @@ void copy_to_fs(addr_t dst, void *src, size_t len);
228void *copy_from_fs(void *dst, addr_t src, size_t len); 220void *copy_from_fs(void *dst, addr_t src, size_t len);
229void copy_to_gs(addr_t dst, void *src, size_t len); 221void copy_to_gs(addr_t dst, void *src, size_t len);
230void *copy_from_gs(void *dst, addr_t src, size_t len); 222void *copy_from_gs(void *dst, addr_t src, size_t len);
231void *memcpy(void *dst, void *src, size_t len);
232void *memset(void *dst, int c, size_t len);
233
234#define memcpy(d,s,l) __builtin_memcpy(d,s,l)
235#define memset(d,c,l) __builtin_memset(d,c,l)
236 223
237/* a20.c */ 224/* a20.c */
238int enable_a20(void); 225int enable_a20(void);
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index a7677babf946..1e6146137f8e 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -19,10 +19,272 @@
19 19
20static efi_system_table_t *sys_table; 20static efi_system_table_t *sys_table;
21 21
22static struct efi_config *efi_early;
23
24#define efi_call_early(f, ...) \
25 efi_early->call(efi_early->f, __VA_ARGS__);
26
27#define BOOT_SERVICES(bits) \
28static void setup_boot_services##bits(struct efi_config *c) \
29{ \
30 efi_system_table_##bits##_t *table; \
31 efi_boot_services_##bits##_t *bt; \
32 \
33 table = (typeof(table))sys_table; \
34 \
35 c->text_output = table->con_out; \
36 \
37 bt = (typeof(bt))(unsigned long)(table->boottime); \
38 \
39 c->allocate_pool = bt->allocate_pool; \
40 c->allocate_pages = bt->allocate_pages; \
41 c->get_memory_map = bt->get_memory_map; \
42 c->free_pool = bt->free_pool; \
43 c->free_pages = bt->free_pages; \
44 c->locate_handle = bt->locate_handle; \
45 c->handle_protocol = bt->handle_protocol; \
46 c->exit_boot_services = bt->exit_boot_services; \
47}
48BOOT_SERVICES(32);
49BOOT_SERVICES(64);
22 50
23#include "../../../../drivers/firmware/efi/efi-stub-helper.c" 51static void efi_printk(efi_system_table_t *, char *);
52static void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
53
54static efi_status_t
55__file_size32(void *__fh, efi_char16_t *filename_16,
56 void **handle, u64 *file_sz)
57{
58 efi_file_handle_32_t *h, *fh = __fh;
59 efi_file_info_t *info;
60 efi_status_t status;
61 efi_guid_t info_guid = EFI_FILE_INFO_ID;
62 u32 info_sz;
63
64 status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16,
65 EFI_FILE_MODE_READ, (u64)0);
66 if (status != EFI_SUCCESS) {
67 efi_printk(sys_table, "Failed to open file: ");
68 efi_char16_printk(sys_table, filename_16);
69 efi_printk(sys_table, "\n");
70 return status;
71 }
72
73 *handle = h;
74
75 info_sz = 0;
76 status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
77 &info_sz, NULL);
78 if (status != EFI_BUFFER_TOO_SMALL) {
79 efi_printk(sys_table, "Failed to get file info size\n");
80 return status;
81 }
82
83grow:
84 status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
85 info_sz, (void **)&info);
86 if (status != EFI_SUCCESS) {
87 efi_printk(sys_table, "Failed to alloc mem for file info\n");
88 return status;
89 }
90
91 status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
92 &info_sz, info);
93 if (status == EFI_BUFFER_TOO_SMALL) {
94 efi_call_early(free_pool, info);
95 goto grow;
96 }
97
98 *file_sz = info->file_size;
99 efi_call_early(free_pool, info);
100
101 if (status != EFI_SUCCESS)
102 efi_printk(sys_table, "Failed to get initrd info\n");
103
104 return status;
105}
106
107static efi_status_t
108__file_size64(void *__fh, efi_char16_t *filename_16,
109 void **handle, u64 *file_sz)
110{
111 efi_file_handle_64_t *h, *fh = __fh;
112 efi_file_info_t *info;
113 efi_status_t status;
114 efi_guid_t info_guid = EFI_FILE_INFO_ID;
115 u32 info_sz;
24 116
117 status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16,
118 EFI_FILE_MODE_READ, (u64)0);
119 if (status != EFI_SUCCESS) {
120 efi_printk(sys_table, "Failed to open file: ");
121 efi_char16_printk(sys_table, filename_16);
122 efi_printk(sys_table, "\n");
123 return status;
124 }
25 125
126 *handle = h;
127
128 info_sz = 0;
129 status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
130 &info_sz, NULL);
131 if (status != EFI_BUFFER_TOO_SMALL) {
132 efi_printk(sys_table, "Failed to get file info size\n");
133 return status;
134 }
135
136grow:
137 status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
138 info_sz, (void **)&info);
139 if (status != EFI_SUCCESS) {
140 efi_printk(sys_table, "Failed to alloc mem for file info\n");
141 return status;
142 }
143
144 status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
145 &info_sz, info);
146 if (status == EFI_BUFFER_TOO_SMALL) {
147 efi_call_early(free_pool, info);
148 goto grow;
149 }
150
151 *file_sz = info->file_size;
152 efi_call_early(free_pool, info);
153
154 if (status != EFI_SUCCESS)
155 efi_printk(sys_table, "Failed to get initrd info\n");
156
157 return status;
158}
159static efi_status_t
160efi_file_size(efi_system_table_t *sys_table, void *__fh,
161 efi_char16_t *filename_16, void **handle, u64 *file_sz)
162{
163 if (efi_early->is64)
164 return __file_size64(__fh, filename_16, handle, file_sz);
165
166 return __file_size32(__fh, filename_16, handle, file_sz);
167}
168
169static inline efi_status_t
170efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
171{
172 unsigned long func;
173
174 if (efi_early->is64) {
175 efi_file_handle_64_t *fh = __fh;
176
177 func = (unsigned long)fh->read;
178 return efi_early->call(func, handle, size, addr);
179 } else {
180 efi_file_handle_32_t *fh = __fh;
181
182 func = (unsigned long)fh->read;
183 return efi_early->call(func, handle, size, addr);
184 }
185}
186
187static inline efi_status_t efi_file_close(void *__fh, void *handle)
188{
189 if (efi_early->is64) {
190 efi_file_handle_64_t *fh = __fh;
191
192 return efi_early->call((unsigned long)fh->close, handle);
193 } else {
194 efi_file_handle_32_t *fh = __fh;
195
196 return efi_early->call((unsigned long)fh->close, handle);
197 }
198}
199
200static inline efi_status_t __open_volume32(void *__image, void **__fh)
201{
202 efi_file_io_interface_t *io;
203 efi_loaded_image_32_t *image = __image;
204 efi_file_handle_32_t *fh;
205 efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
206 efi_status_t status;
207 void *handle = (void *)(unsigned long)image->device_handle;
208 unsigned long func;
209
210 status = efi_call_early(handle_protocol, handle,
211 &fs_proto, (void **)&io);
212 if (status != EFI_SUCCESS) {
213 efi_printk(sys_table, "Failed to handle fs_proto\n");
214 return status;
215 }
216
217 func = (unsigned long)io->open_volume;
218 status = efi_early->call(func, io, &fh);
219 if (status != EFI_SUCCESS)
220 efi_printk(sys_table, "Failed to open volume\n");
221
222 *__fh = fh;
223 return status;
224}
225
226static inline efi_status_t __open_volume64(void *__image, void **__fh)
227{
228 efi_file_io_interface_t *io;
229 efi_loaded_image_64_t *image = __image;
230 efi_file_handle_64_t *fh;
231 efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
232 efi_status_t status;
233 void *handle = (void *)(unsigned long)image->device_handle;
234 unsigned long func;
235
236 status = efi_call_early(handle_protocol, handle,
237 &fs_proto, (void **)&io);
238 if (status != EFI_SUCCESS) {
239 efi_printk(sys_table, "Failed to handle fs_proto\n");
240 return status;
241 }
242
243 func = (unsigned long)io->open_volume;
244 status = efi_early->call(func, io, &fh);
245 if (status != EFI_SUCCESS)
246 efi_printk(sys_table, "Failed to open volume\n");
247
248 *__fh = fh;
249 return status;
250}
251
252static inline efi_status_t
253efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
254{
255 if (efi_early->is64)
256 return __open_volume64(__image, __fh);
257
258 return __open_volume32(__image, __fh);
259}
260
261static void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
262{
263 unsigned long output_string;
264 size_t offset;
265
266 if (efi_early->is64) {
267 struct efi_simple_text_output_protocol_64 *out;
268 u64 *func;
269
270 offset = offsetof(typeof(*out), output_string);
271 output_string = efi_early->text_output + offset;
272 func = (u64 *)output_string;
273
274 efi_early->call(*func, efi_early->text_output, str);
275 } else {
276 struct efi_simple_text_output_protocol_32 *out;
277 u32 *func;
278
279 offset = offsetof(typeof(*out), output_string);
280 output_string = efi_early->text_output + offset;
281 func = (u32 *)output_string;
282
283 efi_early->call(*func, efi_early->text_output, str);
284 }
285}
286
287#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
26 288
27static void find_bits(unsigned long mask, u8 *pos, u8 *size) 289static void find_bits(unsigned long mask, u8 *pos, u8 *size)
28{ 290{
@@ -47,105 +309,97 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
47 *size = len; 309 *size = len;
48} 310}
49 311
50static efi_status_t setup_efi_pci(struct boot_params *params) 312static efi_status_t
313__setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
51{ 314{
52 efi_pci_io_protocol *pci; 315 struct pci_setup_rom *rom = NULL;
53 efi_status_t status; 316 efi_status_t status;
54 void **pci_handle; 317 unsigned long size;
55 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; 318 uint64_t attributes;
56 unsigned long nr_pci, size = 0;
57 int i;
58 struct setup_data *data;
59 319
60 data = (struct setup_data *)(unsigned long)params->hdr.setup_data; 320 status = efi_early->call(pci->attributes, pci,
321 EfiPciIoAttributeOperationGet, 0, 0,
322 &attributes);
323 if (status != EFI_SUCCESS)
324 return status;
61 325
62 while (data && data->next) 326 if (!pci->romimage || !pci->romsize)
63 data = (struct setup_data *)(unsigned long)data->next; 327 return EFI_INVALID_PARAMETER;
64 328
65 status = efi_call_phys5(sys_table->boottime->locate_handle, 329 size = pci->romsize + sizeof(*rom);
66 EFI_LOCATE_BY_PROTOCOL, &pci_proto,
67 NULL, &size, pci_handle);
68 330
69 if (status == EFI_BUFFER_TOO_SMALL) { 331 status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
70 status = efi_call_phys3(sys_table->boottime->allocate_pool, 332 if (status != EFI_SUCCESS)
71 EFI_LOADER_DATA, size, &pci_handle); 333 return status;
72 334
73 if (status != EFI_SUCCESS) 335 memset(rom, 0, sizeof(*rom));
74 return status;
75 336
76 status = efi_call_phys5(sys_table->boottime->locate_handle, 337 rom->data.type = SETUP_PCI;
77 EFI_LOCATE_BY_PROTOCOL, &pci_proto, 338 rom->data.len = size - sizeof(struct setup_data);
78 NULL, &size, pci_handle); 339 rom->data.next = 0;
79 } 340 rom->pcilen = pci->romsize;
341 *__rom = rom;
80 342
81 if (status != EFI_SUCCESS) 343 status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
82 goto free_handle; 344 PCI_VENDOR_ID, 1, &(rom->vendor));
83
84 nr_pci = size / sizeof(void *);
85 for (i = 0; i < nr_pci; i++) {
86 void *h = pci_handle[i];
87 uint64_t attributes;
88 struct pci_setup_rom *rom;
89 345
90 status = efi_call_phys3(sys_table->boottime->handle_protocol, 346 if (status != EFI_SUCCESS)
91 h, &pci_proto, &pci); 347 goto free_struct;
92 348
93 if (status != EFI_SUCCESS) 349 status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
94 continue; 350 PCI_DEVICE_ID, 1, &(rom->devid));
95 351
96 if (!pci) 352 if (status != EFI_SUCCESS)
97 continue; 353 goto free_struct;
98 354
99#ifdef CONFIG_X86_64 355 status = efi_early->call(pci->get_location, pci, &(rom->segment),
100 status = efi_call_phys4(pci->attributes, pci, 356 &(rom->bus), &(rom->device), &(rom->function));
101 EfiPciIoAttributeOperationGet, 0,
102 &attributes);
103#else
104 status = efi_call_phys5(pci->attributes, pci,
105 EfiPciIoAttributeOperationGet, 0, 0,
106 &attributes);
107#endif
108 if (status != EFI_SUCCESS)
109 continue;
110 357
111 if (!pci->romimage || !pci->romsize) 358 if (status != EFI_SUCCESS)
112 continue; 359 goto free_struct;
113 360
114 size = pci->romsize + sizeof(*rom); 361 memcpy(rom->romdata, pci->romimage, pci->romsize);
362 return status;
115 363
116 status = efi_call_phys3(sys_table->boottime->allocate_pool, 364free_struct:
117 EFI_LOADER_DATA, size, &rom); 365 efi_call_early(free_pool, rom);
366 return status;
367}
118 368
119 if (status != EFI_SUCCESS) 369static efi_status_t
120 continue; 370setup_efi_pci32(struct boot_params *params, void **pci_handle,
371 unsigned long size)
372{
373 efi_pci_io_protocol_32 *pci = NULL;
374 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
375 u32 *handles = (u32 *)(unsigned long)pci_handle;
376 efi_status_t status;
377 unsigned long nr_pci;
378 struct setup_data *data;
379 int i;
121 380
122 rom->data.type = SETUP_PCI; 381 data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
123 rom->data.len = size - sizeof(struct setup_data);
124 rom->data.next = 0;
125 rom->pcilen = pci->romsize;
126 382
127 status = efi_call_phys5(pci->pci.read, pci, 383 while (data && data->next)
128 EfiPciIoWidthUint16, PCI_VENDOR_ID, 384 data = (struct setup_data *)(unsigned long)data->next;
129 1, &(rom->vendor));
130 385
131 if (status != EFI_SUCCESS) 386 nr_pci = size / sizeof(u32);
132 goto free_struct; 387 for (i = 0; i < nr_pci; i++) {
388 struct pci_setup_rom *rom = NULL;
389 u32 h = handles[i];
133 390
134 status = efi_call_phys5(pci->pci.read, pci, 391 status = efi_call_early(handle_protocol, h,
135 EfiPciIoWidthUint16, PCI_DEVICE_ID, 392 &pci_proto, (void **)&pci);
136 1, &(rom->devid));
137 393
138 if (status != EFI_SUCCESS) 394 if (status != EFI_SUCCESS)
139 goto free_struct; 395 continue;
140 396
141 status = efi_call_phys5(pci->get_location, pci, 397 if (!pci)
142 &(rom->segment), &(rom->bus), 398 continue;
143 &(rom->device), &(rom->function));
144 399
400 status = __setup_efi_pci32(pci, &rom);
145 if (status != EFI_SUCCESS) 401 if (status != EFI_SUCCESS)
146 goto free_struct; 402 continue;
147
148 memcpy(rom->romdata, pci->romimage, pci->romsize);
149 403
150 if (data) 404 if (data)
151 data->next = (unsigned long)rom; 405 data->next = (unsigned long)rom;
@@ -154,105 +408,155 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
154 408
155 data = (struct setup_data *)rom; 409 data = (struct setup_data *)rom;
156 410
157 continue;
158 free_struct:
159 efi_call_phys1(sys_table->boottime->free_pool, rom);
160 } 411 }
161 412
162free_handle:
163 efi_call_phys1(sys_table->boottime->free_pool, pci_handle);
164 return status; 413 return status;
165} 414}
166 415
167/* 416static efi_status_t
168 * See if we have Graphics Output Protocol 417__setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
169 */
170static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
171 unsigned long size)
172{ 418{
173 struct efi_graphics_output_protocol *gop, *first_gop; 419 struct pci_setup_rom *rom;
174 struct efi_pixel_bitmask pixel_info;
175 unsigned long nr_gops;
176 efi_status_t status; 420 efi_status_t status;
177 void **gop_handle; 421 unsigned long size;
178 u16 width, height; 422 uint64_t attributes;
179 u32 fb_base, fb_size;
180 u32 pixels_per_scan_line;
181 int pixel_format;
182 int i;
183 423
184 status = efi_call_phys3(sys_table->boottime->allocate_pool, 424 status = efi_early->call(pci->attributes, pci,
185 EFI_LOADER_DATA, size, &gop_handle); 425 EfiPciIoAttributeOperationGet, 0,
426 &attributes);
186 if (status != EFI_SUCCESS) 427 if (status != EFI_SUCCESS)
187 return status; 428 return status;
188 429
189 status = efi_call_phys5(sys_table->boottime->locate_handle, 430 if (!pci->romimage || !pci->romsize)
190 EFI_LOCATE_BY_PROTOCOL, proto, 431 return EFI_INVALID_PARAMETER;
191 NULL, &size, gop_handle); 432
433 size = pci->romsize + sizeof(*rom);
434
435 status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
192 if (status != EFI_SUCCESS) 436 if (status != EFI_SUCCESS)
193 goto free_handle; 437 return status;
194 438
195 first_gop = NULL; 439 rom->data.type = SETUP_PCI;
440 rom->data.len = size - sizeof(struct setup_data);
441 rom->data.next = 0;
442 rom->pcilen = pci->romsize;
443 *__rom = rom;
196 444
197 nr_gops = size / sizeof(void *); 445 status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
198 for (i = 0; i < nr_gops; i++) { 446 PCI_VENDOR_ID, 1, &(rom->vendor));
199 struct efi_graphics_output_mode_info *info; 447
200 efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; 448 if (status != EFI_SUCCESS)
201 bool conout_found = false; 449 goto free_struct;
202 void *dummy; 450
203 void *h = gop_handle[i]; 451 status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
452 PCI_DEVICE_ID, 1, &(rom->devid));
453
454 if (status != EFI_SUCCESS)
455 goto free_struct;
456
457 status = efi_early->call(pci->get_location, pci, &(rom->segment),
458 &(rom->bus), &(rom->device), &(rom->function));
459
460 if (status != EFI_SUCCESS)
461 goto free_struct;
462
463 memcpy(rom->romdata, pci->romimage, pci->romsize);
464 return status;
465
466free_struct:
467 efi_call_early(free_pool, rom);
468 return status;
469
470}
471
472static efi_status_t
473setup_efi_pci64(struct boot_params *params, void **pci_handle,
474 unsigned long size)
475{
476 efi_pci_io_protocol_64 *pci = NULL;
477 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
478 u64 *handles = (u64 *)(unsigned long)pci_handle;
479 efi_status_t status;
480 unsigned long nr_pci;
481 struct setup_data *data;
482 int i;
483
484 data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
485
486 while (data && data->next)
487 data = (struct setup_data *)(unsigned long)data->next;
488
489 nr_pci = size / sizeof(u64);
490 for (i = 0; i < nr_pci; i++) {
491 struct pci_setup_rom *rom = NULL;
492 u64 h = handles[i];
493
494 status = efi_call_early(handle_protocol, h,
495 &pci_proto, (void **)&pci);
204 496
205 status = efi_call_phys3(sys_table->boottime->handle_protocol,
206 h, proto, &gop);
207 if (status != EFI_SUCCESS) 497 if (status != EFI_SUCCESS)
208 continue; 498 continue;
209 499
210 status = efi_call_phys3(sys_table->boottime->handle_protocol, 500 if (!pci)
211 h, &conout_proto, &dummy); 501 continue;
212 502
213 if (status == EFI_SUCCESS) 503 status = __setup_efi_pci64(pci, &rom);
214 conout_found = true; 504 if (status != EFI_SUCCESS)
505 continue;
215 506
216 status = efi_call_phys4(gop->query_mode, gop, 507 if (data)
217 gop->mode->mode, &size, &info); 508 data->next = (unsigned long)rom;
218 if (status == EFI_SUCCESS && (!first_gop || conout_found)) { 509 else
219 /* 510 params->hdr.setup_data = (unsigned long)rom;
220 * Systems that use the UEFI Console Splitter may 511
221 * provide multiple GOP devices, not all of which are 512 data = (struct setup_data *)rom;
222 * backed by real hardware. The workaround is to search
223 * for a GOP implementing the ConOut protocol, and if
224 * one isn't found, to just fall back to the first GOP.
225 */
226 width = info->horizontal_resolution;
227 height = info->vertical_resolution;
228 fb_base = gop->mode->frame_buffer_base;
229 fb_size = gop->mode->frame_buffer_size;
230 pixel_format = info->pixel_format;
231 pixel_info = info->pixel_information;
232 pixels_per_scan_line = info->pixels_per_scan_line;
233 513
234 /*
235 * Once we've found a GOP supporting ConOut,
236 * don't bother looking any further.
237 */
238 first_gop = gop;
239 if (conout_found)
240 break;
241 }
242 } 514 }
243 515
244 /* Did we find any GOPs? */ 516 return status;
245 if (!first_gop) 517}
518
519static efi_status_t setup_efi_pci(struct boot_params *params)
520{
521 efi_status_t status;
522 void **pci_handle = NULL;
523 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
524 unsigned long size = 0;
525
526 status = efi_call_early(locate_handle,
527 EFI_LOCATE_BY_PROTOCOL,
528 &pci_proto, NULL, &size, pci_handle);
529
530 if (status == EFI_BUFFER_TOO_SMALL) {
531 status = efi_call_early(allocate_pool,
532 EFI_LOADER_DATA,
533 size, (void **)&pci_handle);
534
535 if (status != EFI_SUCCESS)
536 return status;
537
538 status = efi_call_early(locate_handle,
539 EFI_LOCATE_BY_PROTOCOL, &pci_proto,
540 NULL, &size, pci_handle);
541 }
542
543 if (status != EFI_SUCCESS)
246 goto free_handle; 544 goto free_handle;
247 545
248 /* EFI framebuffer */ 546 if (efi_early->is64)
249 si->orig_video_isVGA = VIDEO_TYPE_EFI; 547 status = setup_efi_pci64(params, pci_handle, size);
548 else
549 status = setup_efi_pci32(params, pci_handle, size);
250 550
251 si->lfb_width = width; 551free_handle:
252 si->lfb_height = height; 552 efi_call_early(free_pool, pci_handle);
253 si->lfb_base = fb_base; 553 return status;
254 si->pages = 1; 554}
255 555
556static void
557setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
558 struct efi_pixel_bitmask pixel_info, int pixel_format)
559{
256 if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { 560 if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
257 si->lfb_depth = 32; 561 si->lfb_depth = 32;
258 si->lfb_linelength = pixels_per_scan_line * 4; 562 si->lfb_linelength = pixels_per_scan_line * 4;
@@ -297,62 +601,319 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
297 si->rsvd_size = 0; 601 si->rsvd_size = 0;
298 si->rsvd_pos = 0; 602 si->rsvd_pos = 0;
299 } 603 }
604}
605
606static efi_status_t
607__gop_query32(struct efi_graphics_output_protocol_32 *gop32,
608 struct efi_graphics_output_mode_info **info,
609 unsigned long *size, u32 *fb_base)
610{
611 struct efi_graphics_output_protocol_mode_32 *mode;
612 efi_status_t status;
613 unsigned long m;
614
615 m = gop32->mode;
616 mode = (struct efi_graphics_output_protocol_mode_32 *)m;
617
618 status = efi_early->call(gop32->query_mode, gop32,
619 mode->mode, size, info);
620 if (status != EFI_SUCCESS)
621 return status;
622
623 *fb_base = mode->frame_buffer_base;
624 return status;
625}
626
627static efi_status_t
628setup_gop32(struct screen_info *si, efi_guid_t *proto,
629 unsigned long size, void **gop_handle)
630{
631 struct efi_graphics_output_protocol_32 *gop32, *first_gop;
632 unsigned long nr_gops;
633 u16 width, height;
634 u32 pixels_per_scan_line;
635 u32 fb_base;
636 struct efi_pixel_bitmask pixel_info;
637 int pixel_format;
638 efi_status_t status;
639 u32 *handles = (u32 *)(unsigned long)gop_handle;
640 int i;
641
642 first_gop = NULL;
643 gop32 = NULL;
644
645 nr_gops = size / sizeof(u32);
646 for (i = 0; i < nr_gops; i++) {
647 struct efi_graphics_output_mode_info *info = NULL;
648 efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
649 bool conout_found = false;
650 void *dummy = NULL;
651 u32 h = handles[i];
652
653 status = efi_call_early(handle_protocol, h,
654 proto, (void **)&gop32);
655 if (status != EFI_SUCCESS)
656 continue;
657
658 status = efi_call_early(handle_protocol, h,
659 &conout_proto, &dummy);
660 if (status == EFI_SUCCESS)
661 conout_found = true;
662
663 status = __gop_query32(gop32, &info, &size, &fb_base);
664 if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
665 /*
666 * Systems that use the UEFI Console Splitter may
667 * provide multiple GOP devices, not all of which are
668 * backed by real hardware. The workaround is to search
669 * for a GOP implementing the ConOut protocol, and if
670 * one isn't found, to just fall back to the first GOP.
671 */
672 width = info->horizontal_resolution;
673 height = info->vertical_resolution;
674 pixel_format = info->pixel_format;
675 pixel_info = info->pixel_information;
676 pixels_per_scan_line = info->pixels_per_scan_line;
677
678 /*
679 * Once we've found a GOP supporting ConOut,
680 * don't bother looking any further.
681 */
682 first_gop = gop32;
683 if (conout_found)
684 break;
685 }
686 }
687
688 /* Did we find any GOPs? */
689 if (!first_gop)
690 goto out;
691
692 /* EFI framebuffer */
693 si->orig_video_isVGA = VIDEO_TYPE_EFI;
694
695 si->lfb_width = width;
696 si->lfb_height = height;
697 si->lfb_base = fb_base;
698 si->pages = 1;
699
700 setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
300 701
301 si->lfb_size = si->lfb_linelength * si->lfb_height; 702 si->lfb_size = si->lfb_linelength * si->lfb_height;
302 703
303 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; 704 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
705out:
706 return status;
707}
304 708
305free_handle: 709static efi_status_t
306 efi_call_phys1(sys_table->boottime->free_pool, gop_handle); 710__gop_query64(struct efi_graphics_output_protocol_64 *gop64,
711 struct efi_graphics_output_mode_info **info,
712 unsigned long *size, u32 *fb_base)
713{
714 struct efi_graphics_output_protocol_mode_64 *mode;
715 efi_status_t status;
716 unsigned long m;
717
718 m = gop64->mode;
719 mode = (struct efi_graphics_output_protocol_mode_64 *)m;
720
721 status = efi_early->call(gop64->query_mode, gop64,
722 mode->mode, size, info);
723 if (status != EFI_SUCCESS)
724 return status;
725
726 *fb_base = mode->frame_buffer_base;
727 return status;
728}
729
730static efi_status_t
731setup_gop64(struct screen_info *si, efi_guid_t *proto,
732 unsigned long size, void **gop_handle)
733{
734 struct efi_graphics_output_protocol_64 *gop64, *first_gop;
735 unsigned long nr_gops;
736 u16 width, height;
737 u32 pixels_per_scan_line;
738 u32 fb_base;
739 struct efi_pixel_bitmask pixel_info;
740 int pixel_format;
741 efi_status_t status;
742 u64 *handles = (u64 *)(unsigned long)gop_handle;
743 int i;
744
745 first_gop = NULL;
746 gop64 = NULL;
747
748 nr_gops = size / sizeof(u64);
749 for (i = 0; i < nr_gops; i++) {
750 struct efi_graphics_output_mode_info *info = NULL;
751 efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
752 bool conout_found = false;
753 void *dummy = NULL;
754 u64 h = handles[i];
755
756 status = efi_call_early(handle_protocol, h,
757 proto, (void **)&gop64);
758 if (status != EFI_SUCCESS)
759 continue;
760
761 status = efi_call_early(handle_protocol, h,
762 &conout_proto, &dummy);
763 if (status == EFI_SUCCESS)
764 conout_found = true;
765
766 status = __gop_query64(gop64, &info, &size, &fb_base);
767 if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
768 /*
769 * Systems that use the UEFI Console Splitter may
770 * provide multiple GOP devices, not all of which are
771 * backed by real hardware. The workaround is to search
772 * for a GOP implementing the ConOut protocol, and if
773 * one isn't found, to just fall back to the first GOP.
774 */
775 width = info->horizontal_resolution;
776 height = info->vertical_resolution;
777 pixel_format = info->pixel_format;
778 pixel_info = info->pixel_information;
779 pixels_per_scan_line = info->pixels_per_scan_line;
780
781 /*
782 * Once we've found a GOP supporting ConOut,
783 * don't bother looking any further.
784 */
785 first_gop = gop64;
786 if (conout_found)
787 break;
788 }
789 }
790
791 /* Did we find any GOPs? */
792 if (!first_gop)
793 goto out;
794
795 /* EFI framebuffer */
796 si->orig_video_isVGA = VIDEO_TYPE_EFI;
797
798 si->lfb_width = width;
799 si->lfb_height = height;
800 si->lfb_base = fb_base;
801 si->pages = 1;
802
803 setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
804
805 si->lfb_size = si->lfb_linelength * si->lfb_height;
806
807 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
808out:
307 return status; 809 return status;
308} 810}
309 811
310/* 812/*
311 * See if we have Universal Graphics Adapter (UGA) protocol 813 * See if we have Graphics Output Protocol
312 */ 814 */
313static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto, 815static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
314 unsigned long size) 816 unsigned long size)
315{ 817{
316 struct efi_uga_draw_protocol *uga, *first_uga;
317 unsigned long nr_ugas;
318 efi_status_t status; 818 efi_status_t status;
319 u32 width, height; 819 void **gop_handle = NULL;
320 void **uga_handle = NULL;
321 int i;
322 820
323 status = efi_call_phys3(sys_table->boottime->allocate_pool, 821 status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
324 EFI_LOADER_DATA, size, &uga_handle); 822 size, (void **)&gop_handle);
325 if (status != EFI_SUCCESS) 823 if (status != EFI_SUCCESS)
326 return status; 824 return status;
327 825
328 status = efi_call_phys5(sys_table->boottime->locate_handle, 826 status = efi_call_early(locate_handle,
329 EFI_LOCATE_BY_PROTOCOL, uga_proto, 827 EFI_LOCATE_BY_PROTOCOL,
330 NULL, &size, uga_handle); 828 proto, NULL, &size, gop_handle);
331 if (status != EFI_SUCCESS) 829 if (status != EFI_SUCCESS)
332 goto free_handle; 830 goto free_handle;
333 831
832 if (efi_early->is64)
833 status = setup_gop64(si, proto, size, gop_handle);
834 else
835 status = setup_gop32(si, proto, size, gop_handle);
836
837free_handle:
838 efi_call_early(free_pool, gop_handle);
839 return status;
840}
841
842static efi_status_t
843setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
844{
845 struct efi_uga_draw_protocol *uga = NULL, *first_uga;
846 efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
847 unsigned long nr_ugas;
848 u32 *handles = (u32 *)uga_handle;;
849 efi_status_t status;
850 int i;
851
334 first_uga = NULL; 852 first_uga = NULL;
853 nr_ugas = size / sizeof(u32);
854 for (i = 0; i < nr_ugas; i++) {
855 efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
856 u32 w, h, depth, refresh;
857 void *pciio;
858 u32 handle = handles[i];
859
860 status = efi_call_early(handle_protocol, handle,
861 &uga_proto, (void **)&uga);
862 if (status != EFI_SUCCESS)
863 continue;
864
865 efi_call_early(handle_protocol, handle, &pciio_proto, &pciio);
866
867 status = efi_early->call((unsigned long)uga->get_mode, uga,
868 &w, &h, &depth, &refresh);
869 if (status == EFI_SUCCESS && (!first_uga || pciio)) {
870 *width = w;
871 *height = h;
872
873 /*
874 * Once we've found a UGA supporting PCIIO,
875 * don't bother looking any further.
876 */
877 if (pciio)
878 break;
335 879
336 nr_ugas = size / sizeof(void *); 880 first_uga = uga;
881 }
882 }
883
884 return status;
885}
886
887static efi_status_t
888setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height)
889{
890 struct efi_uga_draw_protocol *uga = NULL, *first_uga;
891 efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
892 unsigned long nr_ugas;
893 u64 *handles = (u64 *)uga_handle;;
894 efi_status_t status;
895 int i;
896
897 first_uga = NULL;
898 nr_ugas = size / sizeof(u64);
337 for (i = 0; i < nr_ugas; i++) { 899 for (i = 0; i < nr_ugas; i++) {
338 efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; 900 efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
339 void *handle = uga_handle[i];
340 u32 w, h, depth, refresh; 901 u32 w, h, depth, refresh;
341 void *pciio; 902 void *pciio;
903 u64 handle = handles[i];
342 904
343 status = efi_call_phys3(sys_table->boottime->handle_protocol, 905 status = efi_call_early(handle_protocol, handle,
344 handle, uga_proto, &uga); 906 &uga_proto, (void **)&uga);
345 if (status != EFI_SUCCESS) 907 if (status != EFI_SUCCESS)
346 continue; 908 continue;
347 909
348 efi_call_phys3(sys_table->boottime->handle_protocol, 910 efi_call_early(handle_protocol, handle, &pciio_proto, &pciio);
349 handle, &pciio_proto, &pciio);
350 911
351 status = efi_call_phys5(uga->get_mode, uga, &w, &h, 912 status = efi_early->call((unsigned long)uga->get_mode, uga,
352 &depth, &refresh); 913 &w, &h, &depth, &refresh);
353 if (status == EFI_SUCCESS && (!first_uga || pciio)) { 914 if (status == EFI_SUCCESS && (!first_uga || pciio)) {
354 width = w; 915 *width = w;
355 height = h; 916 *height = h;
356 917
357 /* 918 /*
358 * Once we've found a UGA supporting PCIIO, 919 * Once we've found a UGA supporting PCIIO,
@@ -365,7 +926,39 @@ static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto,
365 } 926 }
366 } 927 }
367 928
368 if (!first_uga) 929 return status;
930}
931
932/*
933 * See if we have Universal Graphics Adapter (UGA) protocol
934 */
935static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto,
936 unsigned long size)
937{
938 efi_status_t status;
939 u32 width, height;
940 void **uga_handle = NULL;
941
942 status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
943 size, (void **)&uga_handle);
944 if (status != EFI_SUCCESS)
945 return status;
946
947 status = efi_call_early(locate_handle,
948 EFI_LOCATE_BY_PROTOCOL,
949 uga_proto, NULL, &size, uga_handle);
950 if (status != EFI_SUCCESS)
951 goto free_handle;
952
953 height = 0;
954 width = 0;
955
956 if (efi_early->is64)
957 status = setup_uga64(uga_handle, size, &width, &height);
958 else
959 status = setup_uga32(uga_handle, size, &width, &height);
960
961 if (!width && !height)
369 goto free_handle; 962 goto free_handle;
370 963
371 /* EFI framebuffer */ 964 /* EFI framebuffer */
@@ -384,9 +977,8 @@ static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto,
384 si->rsvd_size = 8; 977 si->rsvd_size = 8;
385 si->rsvd_pos = 24; 978 si->rsvd_pos = 24;
386 979
387
388free_handle: 980free_handle:
389 efi_call_phys1(sys_table->boottime->free_pool, uga_handle); 981 efi_call_early(free_pool, uga_handle);
390 return status; 982 return status;
391} 983}
392 984
@@ -404,29 +996,28 @@ void setup_graphics(struct boot_params *boot_params)
404 memset(si, 0, sizeof(*si)); 996 memset(si, 0, sizeof(*si));
405 997
406 size = 0; 998 size = 0;
407 status = efi_call_phys5(sys_table->boottime->locate_handle, 999 status = efi_call_early(locate_handle,
408 EFI_LOCATE_BY_PROTOCOL, &graphics_proto, 1000 EFI_LOCATE_BY_PROTOCOL,
409 NULL, &size, gop_handle); 1001 &graphics_proto, NULL, &size, gop_handle);
410 if (status == EFI_BUFFER_TOO_SMALL) 1002 if (status == EFI_BUFFER_TOO_SMALL)
411 status = setup_gop(si, &graphics_proto, size); 1003 status = setup_gop(si, &graphics_proto, size);
412 1004
413 if (status != EFI_SUCCESS) { 1005 if (status != EFI_SUCCESS) {
414 size = 0; 1006 size = 0;
415 status = efi_call_phys5(sys_table->boottime->locate_handle, 1007 status = efi_call_early(locate_handle,
416 EFI_LOCATE_BY_PROTOCOL, &uga_proto, 1008 EFI_LOCATE_BY_PROTOCOL,
417 NULL, &size, uga_handle); 1009 &uga_proto, NULL, &size, uga_handle);
418 if (status == EFI_BUFFER_TOO_SMALL) 1010 if (status == EFI_BUFFER_TOO_SMALL)
419 setup_uga(si, &uga_proto, size); 1011 setup_uga(si, &uga_proto, size);
420 } 1012 }
421} 1013}
422 1014
423
424/* 1015/*
425 * Because the x86 boot code expects to be passed a boot_params we 1016 * Because the x86 boot code expects to be passed a boot_params we
426 * need to create one ourselves (usually the bootloader would create 1017 * need to create one ourselves (usually the bootloader would create
427 * one for us). 1018 * one for us).
428 */ 1019 */
429struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) 1020struct boot_params *make_boot_params(struct efi_config *c)
430{ 1021{
431 struct boot_params *boot_params; 1022 struct boot_params *boot_params;
432 struct sys_desc_table *sdt; 1023 struct sys_desc_table *sdt;
@@ -434,7 +1025,7 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
434 struct setup_header *hdr; 1025 struct setup_header *hdr;
435 struct efi_info *efi; 1026 struct efi_info *efi;
436 efi_loaded_image_t *image; 1027 efi_loaded_image_t *image;
437 void *options; 1028 void *options, *handle;
438 efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; 1029 efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
439 int options_size = 0; 1030 int options_size = 0;
440 efi_status_t status; 1031 efi_status_t status;
@@ -445,14 +1036,21 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
445 unsigned long ramdisk_addr; 1036 unsigned long ramdisk_addr;
446 unsigned long ramdisk_size; 1037 unsigned long ramdisk_size;
447 1038
448 sys_table = _table; 1039 efi_early = c;
1040 sys_table = (efi_system_table_t *)(unsigned long)efi_early->table;
1041 handle = (void *)(unsigned long)efi_early->image_handle;
449 1042
450 /* Check if we were booted by the EFI firmware */ 1043 /* Check if we were booted by the EFI firmware */
451 if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) 1044 if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
452 return NULL; 1045 return NULL;
453 1046
454 status = efi_call_phys3(sys_table->boottime->handle_protocol, 1047 if (efi_early->is64)
455 handle, &proto, (void *)&image); 1048 setup_boot_services64(efi_early);
1049 else
1050 setup_boot_services32(efi_early);
1051
1052 status = efi_call_early(handle_protocol, handle,
1053 &proto, (void *)&image);
456 if (status != EFI_SUCCESS) { 1054 if (status != EFI_SUCCESS) {
457 efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); 1055 efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
458 return NULL; 1056 return NULL;
@@ -641,14 +1239,13 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext,
641 sizeof(struct e820entry) * nr_desc; 1239 sizeof(struct e820entry) * nr_desc;
642 1240
643 if (*e820ext) { 1241 if (*e820ext) {
644 efi_call_phys1(sys_table->boottime->free_pool, *e820ext); 1242 efi_call_early(free_pool, *e820ext);
645 *e820ext = NULL; 1243 *e820ext = NULL;
646 *e820ext_size = 0; 1244 *e820ext_size = 0;
647 } 1245 }
648 1246
649 status = efi_call_phys3(sys_table->boottime->allocate_pool, 1247 status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
650 EFI_LOADER_DATA, size, e820ext); 1248 size, (void **)e820ext);
651
652 if (status == EFI_SUCCESS) 1249 if (status == EFI_SUCCESS)
653 *e820ext_size = size; 1250 *e820ext_size = size;
654 1251
@@ -656,12 +1253,13 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext,
656} 1253}
657 1254
658static efi_status_t exit_boot(struct boot_params *boot_params, 1255static efi_status_t exit_boot(struct boot_params *boot_params,
659 void *handle) 1256 void *handle, bool is64)
660{ 1257{
661 struct efi_info *efi = &boot_params->efi_info; 1258 struct efi_info *efi = &boot_params->efi_info;
662 unsigned long map_sz, key, desc_size; 1259 unsigned long map_sz, key, desc_size;
663 efi_memory_desc_t *mem_map; 1260 efi_memory_desc_t *mem_map;
664 struct setup_data *e820ext; 1261 struct setup_data *e820ext;
1262 const char *signature;
665 __u32 e820ext_size; 1263 __u32 e820ext_size;
666 __u32 nr_desc, prev_nr_desc; 1264 __u32 nr_desc, prev_nr_desc;
667 efi_status_t status; 1265 efi_status_t status;
@@ -691,11 +1289,13 @@ get_map:
691 if (status != EFI_SUCCESS) 1289 if (status != EFI_SUCCESS)
692 goto free_mem_map; 1290 goto free_mem_map;
693 1291
694 efi_call_phys1(sys_table->boottime->free_pool, mem_map); 1292 efi_call_early(free_pool, mem_map);
695 goto get_map; /* Allocated memory, get map again */ 1293 goto get_map; /* Allocated memory, get map again */
696 } 1294 }
697 1295
698 memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32)); 1296 signature = is64 ? EFI64_LOADER_SIGNATURE : EFI32_LOADER_SIGNATURE;
1297 memcpy(&efi->efi_loader_signature, signature, sizeof(__u32));
1298
699 efi->efi_systab = (unsigned long)sys_table; 1299 efi->efi_systab = (unsigned long)sys_table;
700 efi->efi_memdesc_size = desc_size; 1300 efi->efi_memdesc_size = desc_size;
701 efi->efi_memdesc_version = desc_version; 1301 efi->efi_memdesc_version = desc_version;
@@ -708,8 +1308,7 @@ get_map:
708#endif 1308#endif
709 1309
710 /* Might as well exit boot services now */ 1310 /* Might as well exit boot services now */
711 status = efi_call_phys2(sys_table->boottime->exit_boot_services, 1311 status = efi_call_early(exit_boot_services, handle, key);
712 handle, key);
713 if (status != EFI_SUCCESS) { 1312 if (status != EFI_SUCCESS) {
714 /* 1313 /*
715 * ExitBootServices() will fail if any of the event 1314 * ExitBootServices() will fail if any of the event
@@ -722,7 +1321,7 @@ get_map:
722 goto free_mem_map; 1321 goto free_mem_map;
723 1322
724 called_exit = true; 1323 called_exit = true;
725 efi_call_phys1(sys_table->boottime->free_pool, mem_map); 1324 efi_call_early(free_pool, mem_map);
726 goto get_map; 1325 goto get_map;
727 } 1326 }
728 1327
@@ -736,23 +1335,31 @@ get_map:
736 return EFI_SUCCESS; 1335 return EFI_SUCCESS;
737 1336
738free_mem_map: 1337free_mem_map:
739 efi_call_phys1(sys_table->boottime->free_pool, mem_map); 1338 efi_call_early(free_pool, mem_map);
740 return status; 1339 return status;
741} 1340}
742 1341
743
744/* 1342/*
745 * On success we return a pointer to a boot_params structure, and NULL 1343 * On success we return a pointer to a boot_params structure, and NULL
746 * on failure. 1344 * on failure.
747 */ 1345 */
748struct boot_params *efi_main(void *handle, efi_system_table_t *_table, 1346struct boot_params *efi_main(struct efi_config *c,
749 struct boot_params *boot_params) 1347 struct boot_params *boot_params)
750{ 1348{
751 struct desc_ptr *gdt; 1349 struct desc_ptr *gdt = NULL;
752 efi_loaded_image_t *image; 1350 efi_loaded_image_t *image;
753 struct setup_header *hdr = &boot_params->hdr; 1351 struct setup_header *hdr = &boot_params->hdr;
754 efi_status_t status; 1352 efi_status_t status;
755 struct desc_struct *desc; 1353 struct desc_struct *desc;
1354 void *handle;
1355 efi_system_table_t *_table;
1356 bool is64;
1357
1358 efi_early = c;
1359
1360 _table = (efi_system_table_t *)(unsigned long)efi_early->table;
1361 handle = (void *)(unsigned long)efi_early->image_handle;
1362 is64 = efi_early->is64;
756 1363
757 sys_table = _table; 1364 sys_table = _table;
758 1365
@@ -760,13 +1367,17 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
760 if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) 1367 if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
761 goto fail; 1368 goto fail;
762 1369
1370 if (is64)
1371 setup_boot_services64(efi_early);
1372 else
1373 setup_boot_services32(efi_early);
1374
763 setup_graphics(boot_params); 1375 setup_graphics(boot_params);
764 1376
765 setup_efi_pci(boot_params); 1377 setup_efi_pci(boot_params);
766 1378
767 status = efi_call_phys3(sys_table->boottime->allocate_pool, 1379 status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
768 EFI_LOADER_DATA, sizeof(*gdt), 1380 sizeof(*gdt), (void **)&gdt);
769 (void **)&gdt);
770 if (status != EFI_SUCCESS) { 1381 if (status != EFI_SUCCESS) {
771 efi_printk(sys_table, "Failed to alloc mem for gdt structure\n"); 1382 efi_printk(sys_table, "Failed to alloc mem for gdt structure\n");
772 goto fail; 1383 goto fail;
@@ -797,7 +1408,7 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
797 hdr->code32_start = bzimage_addr; 1408 hdr->code32_start = bzimage_addr;
798 } 1409 }
799 1410
800 status = exit_boot(boot_params, handle); 1411 status = exit_boot(boot_params, handle, is64);
801 if (status != EFI_SUCCESS) 1412 if (status != EFI_SUCCESS)
802 goto fail; 1413 goto fail;
803 1414
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
index 81b6b652b46a..c88c31ecad12 100644
--- a/arch/x86/boot/compressed/eboot.h
+++ b/arch/x86/boot/compressed/eboot.h
@@ -37,6 +37,24 @@ struct efi_graphics_output_mode_info {
37 u32 pixels_per_scan_line; 37 u32 pixels_per_scan_line;
38} __packed; 38} __packed;
39 39
40struct efi_graphics_output_protocol_mode_32 {
41 u32 max_mode;
42 u32 mode;
43 u32 info;
44 u32 size_of_info;
45 u64 frame_buffer_base;
46 u32 frame_buffer_size;
47} __packed;
48
49struct efi_graphics_output_protocol_mode_64 {
50 u32 max_mode;
51 u32 mode;
52 u64 info;
53 u64 size_of_info;
54 u64 frame_buffer_base;
55 u64 frame_buffer_size;
56} __packed;
57
40struct efi_graphics_output_protocol_mode { 58struct efi_graphics_output_protocol_mode {
41 u32 max_mode; 59 u32 max_mode;
42 u32 mode; 60 u32 mode;
@@ -46,6 +64,20 @@ struct efi_graphics_output_protocol_mode {
46 unsigned long frame_buffer_size; 64 unsigned long frame_buffer_size;
47} __packed; 65} __packed;
48 66
67struct efi_graphics_output_protocol_32 {
68 u32 query_mode;
69 u32 set_mode;
70 u32 blt;
71 u32 mode;
72};
73
74struct efi_graphics_output_protocol_64 {
75 u64 query_mode;
76 u64 set_mode;
77 u64 blt;
78 u64 mode;
79};
80
49struct efi_graphics_output_protocol { 81struct efi_graphics_output_protocol {
50 void *query_mode; 82 void *query_mode;
51 unsigned long set_mode; 83 unsigned long set_mode;
@@ -53,10 +85,38 @@ struct efi_graphics_output_protocol {
53 struct efi_graphics_output_protocol_mode *mode; 85 struct efi_graphics_output_protocol_mode *mode;
54}; 86};
55 87
88struct efi_uga_draw_protocol_32 {
89 u32 get_mode;
90 u32 set_mode;
91 u32 blt;
92};
93
94struct efi_uga_draw_protocol_64 {
95 u64 get_mode;
96 u64 set_mode;
97 u64 blt;
98};
99
56struct efi_uga_draw_protocol { 100struct efi_uga_draw_protocol {
57 void *get_mode; 101 void *get_mode;
58 void *set_mode; 102 void *set_mode;
59 void *blt; 103 void *blt;
60}; 104};
61 105
106struct efi_config {
107 u64 image_handle;
108 u64 table;
109 u64 allocate_pool;
110 u64 allocate_pages;
111 u64 get_memory_map;
112 u64 free_pool;
113 u64 free_pages;
114 u64 locate_handle;
115 u64 handle_protocol;
116 u64 exit_boot_services;
117 u64 text_output;
118 efi_status_t (*call)(unsigned long, ...);
119 bool is64;
120} __packed;
121
62#endif /* BOOT_COMPRESSED_EBOOT_H */ 122#endif /* BOOT_COMPRESSED_EBOOT_H */
diff --git a/arch/x86/boot/compressed/efi_stub_64.S b/arch/x86/boot/compressed/efi_stub_64.S
index cedc60de86eb..7ff3632806b1 100644
--- a/arch/x86/boot/compressed/efi_stub_64.S
+++ b/arch/x86/boot/compressed/efi_stub_64.S
@@ -1 +1,30 @@
1#include <asm/segment.h>
2#include <asm/msr.h>
3#include <asm/processor-flags.h>
4
1#include "../../platform/efi/efi_stub_64.S" 5#include "../../platform/efi/efi_stub_64.S"
6
7#ifdef CONFIG_EFI_MIXED
8 .code64
9 .text
10ENTRY(efi64_thunk)
11 push %rbp
12 push %rbx
13
14 subq $16, %rsp
15 leaq efi_exit32(%rip), %rax
16 movl %eax, 8(%rsp)
17 leaq efi_gdt64(%rip), %rax
18 movl %eax, 4(%rsp)
19 movl %eax, 2(%rax) /* Fixup the gdt base address */
20 leaq efi32_boot_gdt(%rip), %rax
21 movl %eax, (%rsp)
22
23 call __efi64_thunk
24
25 addq $16, %rsp
26 pop %rbx
27 pop %rbp
28 ret
29ENDPROC(efi64_thunk)
30#endif /* CONFIG_EFI_MIXED */
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 9116aac232c7..de9d4200d305 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -42,26 +42,53 @@ ENTRY(startup_32)
42ENTRY(efi_pe_entry) 42ENTRY(efi_pe_entry)
43 add $0x4, %esp 43 add $0x4, %esp
44 44
45 call 1f
461: popl %esi
47 subl $1b, %esi
48
49 popl %ecx
50 movl %ecx, efi32_config(%esi) /* Handle */
51 popl %ecx
52 movl %ecx, efi32_config+8(%esi) /* EFI System table pointer */
53
54 /* Relocate efi_config->call() */
55 leal efi32_config(%esi), %eax
56 add %esi, 88(%eax)
57 pushl %eax
58
45 call make_boot_params 59 call make_boot_params
46 cmpl $0, %eax 60 cmpl $0, %eax
47 je 1f 61 je fail
48 movl 0x4(%esp), %esi 62 popl %ecx
49 movl (%esp), %ecx
50 pushl %eax 63 pushl %eax
51 pushl %esi
52 pushl %ecx 64 pushl %ecx
53 sub $0x4, %esp 65 jmp 2f /* Skip efi_config initialization */
54 66
55ENTRY(efi_stub_entry) 67ENTRY(efi32_stub_entry)
56 add $0x4, %esp 68 add $0x4, %esp
69 popl %ecx
70 popl %edx
71
72 call 1f
731: popl %esi
74 subl $1b, %esi
75
76 movl %ecx, efi32_config(%esi) /* Handle */
77 movl %edx, efi32_config+8(%esi) /* EFI System table pointer */
78
79 /* Relocate efi_config->call() */
80 leal efi32_config(%esi), %eax
81 add %esi, 88(%eax)
82 pushl %eax
832:
57 call efi_main 84 call efi_main
58 cmpl $0, %eax 85 cmpl $0, %eax
59 movl %eax, %esi 86 movl %eax, %esi
60 jne 2f 87 jne 2f
611: 88fail:
62 /* EFI init failed, so hang. */ 89 /* EFI init failed, so hang. */
63 hlt 90 hlt
64 jmp 1b 91 jmp fail
652: 922:
66 call 3f 93 call 3f
673: 943:
@@ -202,6 +229,15 @@ relocated:
202 xorl %ebx, %ebx 229 xorl %ebx, %ebx
203 jmp *%eax 230 jmp *%eax
204 231
232#ifdef CONFIG_EFI_STUB
233 .data
234efi32_config:
235 .fill 11,8,0
236 .long efi_call_phys
237 .long 0
238 .byte 0
239#endif
240
205/* 241/*
206 * Stack and heap for uncompression 242 * Stack and heap for uncompression
207 */ 243 */
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index c5c1ae0997e7..57e58a5fa210 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -113,7 +113,8 @@ ENTRY(startup_32)
113 lgdt gdt(%ebp) 113 lgdt gdt(%ebp)
114 114
115 /* Enable PAE mode */ 115 /* Enable PAE mode */
116 movl $(X86_CR4_PAE), %eax 116 movl %cr4, %eax
117 orl $X86_CR4_PAE, %eax
117 movl %eax, %cr4 118 movl %eax, %cr4
118 119
119 /* 120 /*
@@ -178,6 +179,13 @@ ENTRY(startup_32)
178 */ 179 */
179 pushl $__KERNEL_CS 180 pushl $__KERNEL_CS
180 leal startup_64(%ebp), %eax 181 leal startup_64(%ebp), %eax
182#ifdef CONFIG_EFI_MIXED
183 movl efi32_config(%ebp), %ebx
184 cmp $0, %ebx
185 jz 1f
186 leal handover_entry(%ebp), %eax
1871:
188#endif
181 pushl %eax 189 pushl %eax
182 190
183 /* Enter paged protected Mode, activating Long Mode */ 191 /* Enter paged protected Mode, activating Long Mode */
@@ -188,6 +196,30 @@ ENTRY(startup_32)
188 lret 196 lret
189ENDPROC(startup_32) 197ENDPROC(startup_32)
190 198
199#ifdef CONFIG_EFI_MIXED
200 .org 0x190
201ENTRY(efi32_stub_entry)
202 add $0x4, %esp /* Discard return address */
203 popl %ecx
204 popl %edx
205 popl %esi
206
207 leal (BP_scratch+4)(%esi), %esp
208 call 1f
2091: pop %ebp
210 subl $1b, %ebp
211
212 movl %ecx, efi32_config(%ebp)
213 movl %edx, efi32_config+8(%ebp)
214 sgdtl efi32_boot_gdt(%ebp)
215
216 leal efi32_config(%ebp), %eax
217 movl %eax, efi_config(%ebp)
218
219 jmp startup_32
220ENDPROC(efi32_stub_entry)
221#endif
222
191 .code64 223 .code64
192 .org 0x200 224 .org 0x200
193ENTRY(startup_64) 225ENTRY(startup_64)
@@ -209,26 +241,48 @@ ENTRY(startup_64)
209 jmp preferred_addr 241 jmp preferred_addr
210 242
211ENTRY(efi_pe_entry) 243ENTRY(efi_pe_entry)
212 mov %rcx, %rdi 244 movq %rcx, efi64_config(%rip) /* Handle */
213 mov %rdx, %rsi 245 movq %rdx, efi64_config+8(%rip) /* EFI System table pointer */
214 pushq %rdi 246
215 pushq %rsi 247 leaq efi64_config(%rip), %rax
248 movq %rax, efi_config(%rip)
249
250 call 1f
2511: popq %rbp
252 subq $1b, %rbp
253
254 /*
255 * Relocate efi_config->call().
256 */
257 addq %rbp, efi64_config+88(%rip)
258
259 movq %rax, %rdi
216 call make_boot_params 260 call make_boot_params
217 cmpq $0,%rax 261 cmpq $0,%rax
218 je 1f 262 je fail
219 mov %rax, %rdx 263 mov %rax, %rsi
220 popq %rsi 264 jmp 2f /* Skip the relocation */
221 popq %rdi
222 265
223ENTRY(efi_stub_entry) 266handover_entry:
267 call 1f
2681: popq %rbp
269 subq $1b, %rbp
270
271 /*
272 * Relocate efi_config->call().
273 */
274 movq efi_config(%rip), %rax
275 addq %rbp, 88(%rax)
2762:
277 movq efi_config(%rip), %rdi
224 call efi_main 278 call efi_main
225 movq %rax,%rsi 279 movq %rax,%rsi
226 cmpq $0,%rax 280 cmpq $0,%rax
227 jne 2f 281 jne 2f
2281: 282fail:
229 /* EFI init failed, so hang. */ 283 /* EFI init failed, so hang. */
230 hlt 284 hlt
231 jmp 1b 285 jmp fail
2322: 2862:
233 call 3f 287 call 3f
2343: 2883:
@@ -307,6 +361,20 @@ preferred_addr:
307 leaq relocated(%rbx), %rax 361 leaq relocated(%rbx), %rax
308 jmp *%rax 362 jmp *%rax
309 363
364#ifdef CONFIG_EFI_STUB
365 .org 0x390
366ENTRY(efi64_stub_entry)
367 movq %rdi, efi64_config(%rip) /* Handle */
368 movq %rsi, efi64_config+8(%rip) /* EFI System table pointer */
369
370 leaq efi64_config(%rip), %rax
371 movq %rax, efi_config(%rip)
372
373 movq %rdx, %rsi
374 jmp handover_entry
375ENDPROC(efi64_stub_entry)
376#endif
377
310 .text 378 .text
311relocated: 379relocated:
312 380
@@ -372,6 +440,25 @@ gdt:
372 .quad 0x0000000000000000 /* TS continued */ 440 .quad 0x0000000000000000 /* TS continued */
373gdt_end: 441gdt_end:
374 442
443#ifdef CONFIG_EFI_STUB
444efi_config:
445 .quad 0
446
447#ifdef CONFIG_EFI_MIXED
448 .global efi32_config
449efi32_config:
450 .fill 11,8,0
451 .quad efi64_thunk
452 .byte 0
453#endif
454
455 .global efi64_config
456efi64_config:
457 .fill 11,8,0
458 .quad efi_call6
459 .byte 1
460#endif /* CONFIG_EFI_STUB */
461
375/* 462/*
376 * Stack and heap for uncompression 463 * Stack and heap for uncompression
377 */ 464 */
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 196eaf373a06..17684615374b 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -10,6 +10,7 @@
10 */ 10 */
11 11
12#include "misc.h" 12#include "misc.h"
13#include "../string.h"
13 14
14/* WARNING!! 15/* WARNING!!
15 * This code is compiled with -fPIC and it is relocated dynamically 16 * This code is compiled with -fPIC and it is relocated dynamically
@@ -97,8 +98,14 @@
97 */ 98 */
98#define STATIC static 99#define STATIC static
99 100
100#undef memset
101#undef memcpy 101#undef memcpy
102
103/*
104 * Use a normal definition of memset() from string.c. There are already
105 * included header files which expect a definition of memset() and by
106 * the time we define memset macro, it is too late.
107 */
108#undef memset
102#define memzero(s, n) memset((s), 0, (n)) 109#define memzero(s, n) memset((s), 0, (n))
103 110
104 111
@@ -109,9 +116,6 @@ static void error(char *m);
109 */ 116 */
110struct boot_params *real_mode; /* Pointer to real-mode data */ 117struct boot_params *real_mode; /* Pointer to real-mode data */
111 118
112void *memset(void *s, int c, size_t n);
113void *memcpy(void *dest, const void *src, size_t n);
114
115memptr free_mem_ptr; 119memptr free_mem_ptr;
116memptr free_mem_end_ptr; 120memptr free_mem_end_ptr;
117 121
@@ -216,45 +220,6 @@ void __putstr(const char *s)
216 outb(0xff & (pos >> 1), vidport+1); 220 outb(0xff & (pos >> 1), vidport+1);
217} 221}
218 222
219void *memset(void *s, int c, size_t n)
220{
221 int i;
222 char *ss = s;
223
224 for (i = 0; i < n; i++)
225 ss[i] = c;
226 return s;
227}
228#ifdef CONFIG_X86_32
229void *memcpy(void *dest, const void *src, size_t n)
230{
231 int d0, d1, d2;
232 asm volatile(
233 "rep ; movsl\n\t"
234 "movl %4,%%ecx\n\t"
235 "rep ; movsb\n\t"
236 : "=&c" (d0), "=&D" (d1), "=&S" (d2)
237 : "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src)
238 : "memory");
239
240 return dest;
241}
242#else
243void *memcpy(void *dest, const void *src, size_t n)
244{
245 long d0, d1, d2;
246 asm volatile(
247 "rep ; movsq\n\t"
248 "movq %4,%%rcx\n\t"
249 "rep ; movsb\n\t"
250 : "=&c" (d0), "=&D" (d1), "=&S" (d2)
251 : "0" (n >> 3), "g" (n & 7), "1" (dest), "2" (src)
252 : "memory");
253
254 return dest;
255}
256#endif
257
258static void error(char *x) 223static void error(char *x)
259{ 224{
260 error_putstr("\n\n"); 225 error_putstr("\n\n");
diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c
index ffb9c5c9d748..f3c57e341402 100644
--- a/arch/x86/boot/compressed/string.c
+++ b/arch/x86/boot/compressed/string.c
@@ -1,11 +1,45 @@
1#include "misc.h" 1#include "misc.h"
2#include "../string.c"
3
4/* misc.h might pull in string_32.h which has a macro for memcpy. undef that */
5#undef memcpy
2 6
3int memcmp(const void *s1, const void *s2, size_t len) 7#ifdef CONFIG_X86_32
8void *memcpy(void *dest, const void *src, size_t n)
4{ 9{
5 u8 diff; 10 int d0, d1, d2;
6 asm("repe; cmpsb; setnz %0" 11 asm volatile(
7 : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); 12 "rep ; movsl\n\t"
8 return diff; 13 "movl %4,%%ecx\n\t"
14 "rep ; movsb\n\t"
15 : "=&c" (d0), "=&D" (d1), "=&S" (d2)
16 : "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src)
17 : "memory");
18
19 return dest;
9} 20}
21#else
22void *memcpy(void *dest, const void *src, size_t n)
23{
24 long d0, d1, d2;
25 asm volatile(
26 "rep ; movsq\n\t"
27 "movq %4,%%rcx\n\t"
28 "rep ; movsb\n\t"
29 : "=&c" (d0), "=&D" (d1), "=&S" (d2)
30 : "0" (n >> 3), "g" (n & 7), "1" (dest), "2" (src)
31 : "memory");
10 32
11#include "../string.c" 33 return dest;
34}
35#endif
36
37void *memset(void *s, int c, size_t n)
38{
39 int i;
40 char *ss = s;
41
42 for (i = 0; i < n; i++)
43 ss[i] = c;
44 return s;
45}
diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
index 100a9a10076a..1fd7d575092e 100644
--- a/arch/x86/boot/cpucheck.c
+++ b/arch/x86/boot/cpucheck.c
@@ -27,6 +27,7 @@
27#include <asm/processor-flags.h> 27#include <asm/processor-flags.h>
28#include <asm/required-features.h> 28#include <asm/required-features.h>
29#include <asm/msr-index.h> 29#include <asm/msr-index.h>
30#include "string.h"
30 31
31static u32 err_flags[NCAPINTS]; 32static u32 err_flags[NCAPINTS];
32 33
@@ -67,6 +68,13 @@ static int is_transmeta(void)
67 cpu_vendor[2] == A32('M', 'x', '8', '6'); 68 cpu_vendor[2] == A32('M', 'x', '8', '6');
68} 69}
69 70
71static int is_intel(void)
72{
73 return cpu_vendor[0] == A32('G', 'e', 'n', 'u') &&
74 cpu_vendor[1] == A32('i', 'n', 'e', 'I') &&
75 cpu_vendor[2] == A32('n', 't', 'e', 'l');
76}
77
70/* Returns a bitmask of which words we have error bits in */ 78/* Returns a bitmask of which words we have error bits in */
71static int check_cpuflags(void) 79static int check_cpuflags(void)
72{ 80{
@@ -153,6 +161,19 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
153 asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); 161 asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
154 162
155 err = check_cpuflags(); 163 err = check_cpuflags();
164 } else if (err == 0x01 &&
165 !(err_flags[0] & ~(1 << X86_FEATURE_PAE)) &&
166 is_intel() && cpu.level == 6 &&
167 (cpu.model == 9 || cpu.model == 13)) {
168 /* PAE is disabled on this Pentium M but can be forced */
169 if (cmdline_find_option_bool("forcepae")) {
170 puts("WARNING: Forcing PAE in CPU flags\n");
171 set_bit(X86_FEATURE_PAE, cpu.flags);
172 err = check_cpuflags();
173 }
174 else {
175 puts("WARNING: PAE disabled. Use parameter 'forcepae' to enable at your own risk!\n");
176 }
156 } 177 }
157 178
158 if (err_flags_ptr) 179 if (err_flags_ptr)
diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c
index c501a5b466f8..223e42527077 100644
--- a/arch/x86/boot/edd.c
+++ b/arch/x86/boot/edd.c
@@ -15,6 +15,7 @@
15 15
16#include "boot.h" 16#include "boot.h"
17#include <linux/edd.h> 17#include <linux/edd.h>
18#include "string.h"
18 19
19#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) 20#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
20 21
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index ec3b8ba68096..0ca9a5c362bc 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -283,7 +283,7 @@ _start:
283 # Part 2 of the header, from the old setup.S 283 # Part 2 of the header, from the old setup.S
284 284
285 .ascii "HdrS" # header signature 285 .ascii "HdrS" # header signature
286 .word 0x020c # header version number (>= 0x0105) 286 .word 0x020d # header version number (>= 0x0105)
287 # or else old loadlin-1.5 will fail) 287 # or else old loadlin-1.5 will fail)
288 .globl realmode_swtch 288 .globl realmode_swtch
289realmode_swtch: .word 0, 0 # default_switch, SETUPSEG 289realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
@@ -350,7 +350,7 @@ cmd_line_ptr: .long 0 # (Header version 0x0202 or later)
350 # can be located anywhere in 350 # can be located anywhere in
351 # low memory 0x10000 or higher. 351 # low memory 0x10000 or higher.
352 352
353ramdisk_max: .long 0x7fffffff 353initrd_addr_max: .long 0x7fffffff
354 # (Header version 0x0203 or later) 354 # (Header version 0x0203 or later)
355 # The highest safe address for 355 # The highest safe address for
356 # the contents of an initrd 356 # the contents of an initrd
@@ -375,7 +375,8 @@ xloadflags:
375# define XLF0 0 375# define XLF0 0
376#endif 376#endif
377 377
378#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64) 378#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64) && \
379 !defined(CONFIG_EFI_MIXED)
379 /* kernel/boot_param/ramdisk could be loaded above 4g */ 380 /* kernel/boot_param/ramdisk could be loaded above 4g */
380# define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G 381# define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G
381#else 382#else
@@ -383,10 +384,14 @@ xloadflags:
383#endif 384#endif
384 385
385#ifdef CONFIG_EFI_STUB 386#ifdef CONFIG_EFI_STUB
386# ifdef CONFIG_X86_64 387# ifdef CONFIG_EFI_MIXED
387# define XLF23 XLF_EFI_HANDOVER_64 /* 64-bit EFI handover ok */ 388# define XLF23 (XLF_EFI_HANDOVER_32|XLF_EFI_HANDOVER_64)
388# else 389# else
389# define XLF23 XLF_EFI_HANDOVER_32 /* 32-bit EFI handover ok */ 390# ifdef CONFIG_X86_64
391# define XLF23 XLF_EFI_HANDOVER_64 /* 64-bit EFI handover ok */
392# else
393# define XLF23 XLF_EFI_HANDOVER_32 /* 32-bit EFI handover ok */
394# endif
390# endif 395# endif
391#else 396#else
392# define XLF23 0 397# define XLF23 0
@@ -426,13 +431,7 @@ pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr
426#define INIT_SIZE VO_INIT_SIZE 431#define INIT_SIZE VO_INIT_SIZE
427#endif 432#endif
428init_size: .long INIT_SIZE # kernel initialization size 433init_size: .long INIT_SIZE # kernel initialization size
429handover_offset: 434handover_offset: .long 0 # Filled in by build.c
430#ifdef CONFIG_EFI_STUB
431 .long 0x30 # offset to the handover
432 # protocol entry point
433#else
434 .long 0
435#endif
436 435
437# End of setup header ##################################################### 436# End of setup header #####################################################
438 437
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
index cf6083d444f4..fd6c9f236996 100644
--- a/arch/x86/boot/main.c
+++ b/arch/x86/boot/main.c
@@ -14,6 +14,7 @@
14 */ 14 */
15 15
16#include "boot.h" 16#include "boot.h"
17#include "string.h"
17 18
18struct boot_params boot_params __attribute__((aligned(16))); 19struct boot_params boot_params __attribute__((aligned(16)));
19 20
diff --git a/arch/x86/boot/regs.c b/arch/x86/boot/regs.c
index 958019b1cfa5..c0fb356a3092 100644
--- a/arch/x86/boot/regs.c
+++ b/arch/x86/boot/regs.c
@@ -17,6 +17,7 @@
17 */ 17 */
18 18
19#include "boot.h" 19#include "boot.h"
20#include "string.h"
20 21
21void initregs(struct biosregs *reg) 22void initregs(struct biosregs *reg)
22{ 23{
diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c
index 574dedfe2890..5339040ef86e 100644
--- a/arch/x86/boot/string.c
+++ b/arch/x86/boot/string.c
@@ -14,6 +14,20 @@
14 14
15#include "boot.h" 15#include "boot.h"
16 16
17/*
18 * This file gets included in compressed/string.c which might pull in
19 * string_32.h and which in turn maps memcmp to __builtin_memcmp(). Undo
20 * that first.
21 */
22#undef memcmp
23int memcmp(const void *s1, const void *s2, size_t len)
24{
25 u8 diff;
26 asm("repe; cmpsb; setnz %0"
27 : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
28 return diff;
29}
30
17int strcmp(const char *str1, const char *str2) 31int strcmp(const char *str1, const char *str2)
18{ 32{
19 const unsigned char *s1 = (const unsigned char *)str1; 33 const unsigned char *s1 = (const unsigned char *)str1;
diff --git a/arch/x86/boot/string.h b/arch/x86/boot/string.h
new file mode 100644
index 000000000000..725e820602b1
--- /dev/null
+++ b/arch/x86/boot/string.h
@@ -0,0 +1,21 @@
1#ifndef BOOT_STRING_H
2#define BOOT_STRING_H
3
4/* Undef any of these macros coming from string_32.h. */
5#undef memcpy
6#undef memset
7#undef memcmp
8
9void *memcpy(void *dst, const void *src, size_t len);
10void *memset(void *dst, int c, size_t len);
11int memcmp(const void *s1, const void *s2, size_t len);
12
13/*
14 * Access builtin version by default. If one needs to use optimized version,
15 * do "undef memcpy" in .c file and link against right string.c
16 */
17#define memcpy(d,s,l) __builtin_memcpy(d,s,l)
18#define memset(d,c,l) __builtin_memset(d,c,l)
19#define memcmp __builtin_memcmp
20
21#endif /* BOOT_STRING_H */
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index 8e15b22391fc..1a2f2121cada 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -53,7 +53,8 @@ int is_big_kernel;
53 53
54#define PECOFF_RELOC_RESERVE 0x20 54#define PECOFF_RELOC_RESERVE 0x20
55 55
56unsigned long efi_stub_entry; 56unsigned long efi32_stub_entry;
57unsigned long efi64_stub_entry;
57unsigned long efi_pe_entry; 58unsigned long efi_pe_entry;
58unsigned long startup_64; 59unsigned long startup_64;
59 60
@@ -219,6 +220,52 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
219 update_pecoff_section_header(".text", text_start, text_sz); 220 update_pecoff_section_header(".text", text_start, text_sz);
220} 221}
221 222
223static int reserve_pecoff_reloc_section(int c)
224{
225 /* Reserve 0x20 bytes for .reloc section */
226 memset(buf+c, 0, PECOFF_RELOC_RESERVE);
227 return PECOFF_RELOC_RESERVE;
228}
229
230static void efi_stub_defaults(void)
231{
232 /* Defaults for old kernel */
233#ifdef CONFIG_X86_32
234 efi_pe_entry = 0x10;
235#else
236 efi_pe_entry = 0x210;
237 startup_64 = 0x200;
238#endif
239}
240
241static void efi_stub_entry_update(void)
242{
243 unsigned long addr = efi32_stub_entry;
244
245#ifdef CONFIG_X86_64
246 /* Yes, this is really how we defined it :( */
247 addr = efi64_stub_entry - 0x200;
248#endif
249
250#ifdef CONFIG_EFI_MIXED
251 if (efi32_stub_entry != addr)
252 die("32-bit and 64-bit EFI entry points do not match\n");
253#endif
254 put_unaligned_le32(addr, &buf[0x264]);
255}
256
257#else
258
259static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
260static inline void update_pecoff_text(unsigned int text_start,
261 unsigned int file_sz) {}
262static inline void efi_stub_defaults(void) {}
263static inline void efi_stub_entry_update(void) {}
264
265static inline int reserve_pecoff_reloc_section(int c)
266{
267 return 0;
268}
222#endif /* CONFIG_EFI_STUB */ 269#endif /* CONFIG_EFI_STUB */
223 270
224 271
@@ -250,7 +297,8 @@ static void parse_zoffset(char *fname)
250 p = (char *)buf; 297 p = (char *)buf;
251 298
252 while (p && *p) { 299 while (p && *p) {
253 PARSE_ZOFS(p, efi_stub_entry); 300 PARSE_ZOFS(p, efi32_stub_entry);
301 PARSE_ZOFS(p, efi64_stub_entry);
254 PARSE_ZOFS(p, efi_pe_entry); 302 PARSE_ZOFS(p, efi_pe_entry);
255 PARSE_ZOFS(p, startup_64); 303 PARSE_ZOFS(p, startup_64);
256 304
@@ -271,15 +319,7 @@ int main(int argc, char ** argv)
271 void *kernel; 319 void *kernel;
272 u32 crc = 0xffffffffUL; 320 u32 crc = 0xffffffffUL;
273 321
274 /* Defaults for old kernel */ 322 efi_stub_defaults();
275#ifdef CONFIG_X86_32
276 efi_pe_entry = 0x10;
277 efi_stub_entry = 0x30;
278#else
279 efi_pe_entry = 0x210;
280 efi_stub_entry = 0x230;
281 startup_64 = 0x200;
282#endif
283 323
284 if (argc != 5) 324 if (argc != 5)
285 usage(); 325 usage();
@@ -302,11 +342,7 @@ int main(int argc, char ** argv)
302 die("Boot block hasn't got boot flag (0xAA55)"); 342 die("Boot block hasn't got boot flag (0xAA55)");
303 fclose(file); 343 fclose(file);
304 344
305#ifdef CONFIG_EFI_STUB 345 c += reserve_pecoff_reloc_section(c);
306 /* Reserve 0x20 bytes for .reloc section */
307 memset(buf+c, 0, PECOFF_RELOC_RESERVE);
308 c += PECOFF_RELOC_RESERVE;
309#endif
310 346
311 /* Pad unused space with zeros */ 347 /* Pad unused space with zeros */
312 setup_sectors = (c + 511) / 512; 348 setup_sectors = (c + 511) / 512;
@@ -315,9 +351,7 @@ int main(int argc, char ** argv)
315 i = setup_sectors*512; 351 i = setup_sectors*512;
316 memset(buf+c, 0, i-c); 352 memset(buf+c, 0, i-c);
317 353
318#ifdef CONFIG_EFI_STUB
319 update_pecoff_setup_and_reloc(i); 354 update_pecoff_setup_and_reloc(i);
320#endif
321 355
322 /* Set the default root device */ 356 /* Set the default root device */
323 put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]); 357 put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
@@ -342,14 +376,9 @@ int main(int argc, char ** argv)
342 buf[0x1f1] = setup_sectors-1; 376 buf[0x1f1] = setup_sectors-1;
343 put_unaligned_le32(sys_size, &buf[0x1f4]); 377 put_unaligned_le32(sys_size, &buf[0x1f4]);
344 378
345#ifdef CONFIG_EFI_STUB
346 update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz)); 379 update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz));
347 380
348#ifdef CONFIG_X86_64 /* Yes, this is really how we defined it :( */ 381 efi_stub_entry_update();
349 efi_stub_entry -= 0x200;
350#endif
351 put_unaligned_le32(efi_stub_entry, &buf[0x264]);
352#endif
353 382
354 crc = partial_crc32(buf, i, crc); 383 crc = partial_crc32(buf, i, crc);
355 if (fwrite(buf, 1, i, dest) != i) 384 if (fwrite(buf, 1, i, dest) != i)
diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c
index 11e8c6eb80a1..ba3e100654db 100644
--- a/arch/x86/boot/video-vesa.c
+++ b/arch/x86/boot/video-vesa.c
@@ -16,6 +16,7 @@
16#include "boot.h" 16#include "boot.h"
17#include "video.h" 17#include "video.h"
18#include "vesa.h" 18#include "vesa.h"
19#include "string.h"
19 20
20/* VESA information */ 21/* VESA information */
21static struct vesa_general_info vginfo; 22static struct vesa_general_info vginfo;