forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/arch/x86/boot/tools/build.c
....@@ -53,10 +53,20 @@
5353
5454 #define PECOFF_RELOC_RESERVE 0x20
5555
56
-unsigned long efi32_stub_entry;
57
-unsigned long efi64_stub_entry;
58
-unsigned long efi_pe_entry;
59
-unsigned long startup_64;
56
+#ifdef CONFIG_EFI_MIXED
57
+#define PECOFF_COMPAT_RESERVE 0x20
58
+#else
59
+#define PECOFF_COMPAT_RESERVE 0x0
60
+#endif
61
+
62
+static unsigned long efi32_stub_entry;
63
+static unsigned long efi64_stub_entry;
64
+static unsigned long efi_pe_entry;
65
+static unsigned long efi32_pe_entry;
66
+static unsigned long kernel_info;
67
+static unsigned long startup_64;
68
+static unsigned long _ehead;
69
+static unsigned long _end;
6070
6171 /*----------------------------------------------------------------------*/
6272
....@@ -132,6 +142,7 @@
132142 va_list args;
133143 va_start(args, str);
134144 vfprintf(stderr, str, args);
145
+ va_end(args);
135146 fputc('\n', stderr);
136147 exit(1);
137148 }
....@@ -187,7 +198,10 @@
187198 static void update_pecoff_setup_and_reloc(unsigned int size)
188199 {
189200 u32 setup_offset = 0x200;
190
- u32 reloc_offset = size - PECOFF_RELOC_RESERVE;
201
+ u32 reloc_offset = size - PECOFF_RELOC_RESERVE - PECOFF_COMPAT_RESERVE;
202
+#ifdef CONFIG_EFI_MIXED
203
+ u32 compat_offset = reloc_offset + PECOFF_RELOC_RESERVE;
204
+#endif
191205 u32 setup_size = reloc_offset - setup_offset;
192206
193207 update_pecoff_section_header(".setup", setup_offset, setup_size);
....@@ -199,43 +213,59 @@
199213 */
200214 put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
201215 put_unaligned_le32(10, &buf[reloc_offset + 4]);
216
+
217
+#ifdef CONFIG_EFI_MIXED
218
+ update_pecoff_section_header(".compat", compat_offset, PECOFF_COMPAT_RESERVE);
219
+
220
+ /*
221
+ * Put the IA-32 machine type (0x14c) and the associated entry point
222
+ * address in the .compat section, so loaders can figure out which other
223
+ * execution modes this image supports.
224
+ */
225
+ buf[compat_offset] = 0x1;
226
+ buf[compat_offset + 1] = 0x8;
227
+ put_unaligned_le16(0x14c, &buf[compat_offset + 2]);
228
+ put_unaligned_le32(efi32_pe_entry + size, &buf[compat_offset + 4]);
229
+#endif
202230 }
203231
204
-static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
232
+static void update_pecoff_text(unsigned int text_start, unsigned int file_sz,
233
+ unsigned int init_sz)
205234 {
206235 unsigned int pe_header;
207236 unsigned int text_sz = file_sz - text_start;
237
+ unsigned int bss_sz = init_sz - file_sz;
208238
209239 pe_header = get_unaligned_le32(&buf[0x3c]);
240
+
241
+ /*
242
+ * The PE/COFF loader may load the image at an address which is
243
+ * misaligned with respect to the kernel_alignment field in the setup
244
+ * header.
245
+ *
246
+ * In order to avoid relocating the kernel to correct the misalignment,
247
+ * add slack to allow the buffer to be aligned within the declared size
248
+ * of the image.
249
+ */
250
+ bss_sz += CONFIG_PHYSICAL_ALIGN;
251
+ init_sz += CONFIG_PHYSICAL_ALIGN;
210252
211253 /*
212254 * Size of code: Subtract the size of the first sector (512 bytes)
213255 * which includes the header.
214256 */
215
- put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
257
+ put_unaligned_le32(file_sz - 512 + bss_sz, &buf[pe_header + 0x1c]);
258
+
259
+ /* Size of image */
260
+ put_unaligned_le32(init_sz, &buf[pe_header + 0x50]);
216261
217262 /*
218263 * Address of entry point for PE/COFF executable
219264 */
220265 put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
221266
222
- update_pecoff_section_header(".text", text_start, text_sz);
223
-}
224
-
225
-static void update_pecoff_bss(unsigned int file_sz, unsigned int init_sz)
226
-{
227
- unsigned int pe_header;
228
- unsigned int bss_sz = init_sz - file_sz;
229
-
230
- pe_header = get_unaligned_le32(&buf[0x3c]);
231
-
232
- /* Size of uninitialized data */
233
- put_unaligned_le32(bss_sz, &buf[pe_header + 0x24]);
234
-
235
- /* Size of image */
236
- put_unaligned_le32(init_sz, &buf[pe_header + 0x50]);
237
-
238
- update_pecoff_section_header_fields(".bss", file_sz, bss_sz, 0, 0);
267
+ update_pecoff_section_header_fields(".text", text_start, text_sz + bss_sz,
268
+ text_sz, text_start);
239269 }
240270
241271 static int reserve_pecoff_reloc_section(int c)
....@@ -276,9 +306,8 @@
276306
277307 static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
278308 static inline void update_pecoff_text(unsigned int text_start,
279
- unsigned int file_sz) {}
280
-static inline void update_pecoff_bss(unsigned int file_sz,
281
- unsigned int init_sz) {}
309
+ unsigned int file_sz,
310
+ unsigned int init_sz) {}
282311 static inline void efi_stub_defaults(void) {}
283312 static inline void efi_stub_entry_update(void) {}
284313
....@@ -288,6 +317,12 @@
288317 }
289318 #endif /* CONFIG_EFI_STUB */
290319
320
+static int reserve_pecoff_compat_section(int c)
321
+{
322
+ /* Reserve 0x20 bytes for .compat section */
323
+ memset(buf+c, 0, PECOFF_COMPAT_RESERVE);
324
+ return PECOFF_COMPAT_RESERVE;
325
+}
291326
292327 /*
293328 * Parse zoffset.h and find the entry points. We could just #include zoffset.h
....@@ -320,7 +355,11 @@
320355 PARSE_ZOFS(p, efi32_stub_entry);
321356 PARSE_ZOFS(p, efi64_stub_entry);
322357 PARSE_ZOFS(p, efi_pe_entry);
358
+ PARSE_ZOFS(p, efi32_pe_entry);
359
+ PARSE_ZOFS(p, kernel_info);
323360 PARSE_ZOFS(p, startup_64);
361
+ PARSE_ZOFS(p, _ehead);
362
+ PARSE_ZOFS(p, _end);
324363
325364 p = strchr(p, '\n');
326365 while (p && (*p == '\r' || *p == '\n'))
....@@ -362,6 +401,7 @@
362401 die("Boot block hasn't got boot flag (0xAA55)");
363402 fclose(file);
364403
404
+ c += reserve_pecoff_compat_section(c);
365405 c += reserve_pecoff_reloc_section(c);
366406
367407 /* Pad unused space with zeros */
....@@ -376,8 +416,6 @@
376416 /* Set the default root device */
377417 put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
378418
379
- printf("Setup is %d bytes (padded to %d bytes).\n", c, i);
380
-
381419 /* Open and stat the kernel file */
382420 fd = open(argv[2], O_RDONLY);
383421 if (fd < 0)
....@@ -385,7 +423,6 @@
385423 if (fstat(fd, &sb))
386424 die("Unable to stat `%s': %m", argv[2]);
387425 sz = sb.st_size;
388
- printf("System is %d kB\n", (sz+1023)/1024);
389426 kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
390427 if (kernel == MAP_FAILED)
391428 die("Unable to mmap '%s': %m", argv[2]);
....@@ -403,11 +440,33 @@
403440 buf[0x1f1] = setup_sectors-1;
404441 put_unaligned_le32(sys_size, &buf[0x1f4]);
405442
406
- update_pecoff_text(setup_sectors * 512, i + (sys_size * 16));
407443 init_sz = get_unaligned_le32(&buf[0x260]);
408
- update_pecoff_bss(i + (sys_size * 16), init_sz);
444
+#ifdef CONFIG_EFI_STUB
445
+ /*
446
+ * The decompression buffer will start at ImageBase. When relocating
447
+ * the compressed kernel to its end, we must ensure that the head
448
+ * section does not get overwritten. The head section occupies
449
+ * [i, i + _ehead), and the destination is [init_sz - _end, init_sz).
450
+ *
451
+ * At present these should never overlap, because 'i' is at most 32k
452
+ * because of SETUP_SECT_MAX, '_ehead' is less than 1k, and the
453
+ * calculation of INIT_SIZE in boot/header.S ensures that
454
+ * 'init_sz - _end' is at least 64k.
455
+ *
456
+ * For future-proofing, increase init_sz if necessary.
457
+ */
458
+
459
+ if (init_sz - _end < i + _ehead) {
460
+ init_sz = (i + _ehead + _end + 4095) & ~4095;
461
+ put_unaligned_le32(init_sz, &buf[0x260]);
462
+ }
463
+#endif
464
+ update_pecoff_text(setup_sectors * 512, i + (sys_size * 16), init_sz);
409465
410466 efi_stub_entry_update();
467
+
468
+ /* Update kernel_info offset. */
469
+ put_unaligned_le32(kernel_info, &buf[0x268]);
411470
412471 crc = partial_crc32(buf, i, crc);
413472 if (fwrite(buf, 1, i, dest) != i)
....@@ -426,7 +485,6 @@
426485 }
427486
428487 /* Write the CRC */
429
- printf("CRC %x\n", crc);
430488 put_unaligned_le32(crc, buf);
431489 if (fwrite(buf, 1, 4, dest) != 4)
432490 die("Writing CRC failed");