diff options
Diffstat (limited to 'arch/x86/boot/tools/build.c')
| -rw-r--r-- | arch/x86/boot/tools/build.c | 81 |
1 files changed, 63 insertions, 18 deletions
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index 4b8e165ee572..94c544650020 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c | |||
| @@ -52,6 +52,10 @@ int is_big_kernel; | |||
| 52 | 52 | ||
| 53 | #define PECOFF_RELOC_RESERVE 0x20 | 53 | #define PECOFF_RELOC_RESERVE 0x20 |
| 54 | 54 | ||
| 55 | unsigned long efi_stub_entry; | ||
| 56 | unsigned long efi_pe_entry; | ||
| 57 | unsigned long startup_64; | ||
| 58 | |||
| 55 | /*----------------------------------------------------------------------*/ | 59 | /*----------------------------------------------------------------------*/ |
| 56 | 60 | ||
| 57 | static const u32 crctab32[] = { | 61 | static const u32 crctab32[] = { |
| @@ -132,7 +136,7 @@ static void die(const char * str, ...) | |||
| 132 | 136 | ||
| 133 | static void usage(void) | 137 | static void usage(void) |
| 134 | { | 138 | { |
| 135 | die("Usage: build setup system [> image]"); | 139 | die("Usage: build setup system [zoffset.h] [> image]"); |
| 136 | } | 140 | } |
| 137 | 141 | ||
| 138 | #ifdef CONFIG_EFI_STUB | 142 | #ifdef CONFIG_EFI_STUB |
| @@ -206,30 +210,54 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) | |||
| 206 | */ | 210 | */ |
| 207 | put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]); | 211 | put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]); |
| 208 | 212 | ||
| 209 | #ifdef CONFIG_X86_32 | ||
| 210 | /* | 213 | /* |
| 211 | * Address of entry point. | 214 | * Address of entry point for PE/COFF executable |
| 212 | * | ||
| 213 | * The EFI stub entry point is +16 bytes from the start of | ||
| 214 | * the .text section. | ||
| 215 | */ | 215 | */ |
| 216 | put_unaligned_le32(text_start + 16, &buf[pe_header + 0x28]); | 216 | put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]); |
| 217 | #else | ||
| 218 | /* | ||
| 219 | * Address of entry point. startup_32 is at the beginning and | ||
| 220 | * the 64-bit entry point (startup_64) is always 512 bytes | ||
| 221 | * after. The EFI stub entry point is 16 bytes after that, as | ||
| 222 | * the first instruction allows legacy loaders to jump over | ||
| 223 | * the EFI stub initialisation | ||
| 224 | */ | ||
| 225 | put_unaligned_le32(text_start + 528, &buf[pe_header + 0x28]); | ||
| 226 | #endif /* CONFIG_X86_32 */ | ||
| 227 | 217 | ||
| 228 | update_pecoff_section_header(".text", text_start, text_sz); | 218 | update_pecoff_section_header(".text", text_start, text_sz); |
| 229 | } | 219 | } |
| 230 | 220 | ||
| 231 | #endif /* CONFIG_EFI_STUB */ | 221 | #endif /* CONFIG_EFI_STUB */ |
| 232 | 222 | ||
| 223 | |||
| 224 | /* | ||
| 225 | * Parse zoffset.h and find the entry points. We could just #include zoffset.h | ||
| 226 | * but that would mean tools/build would have to be rebuilt every time. It's | ||
| 227 | * not as if parsing it is hard... | ||
| 228 | */ | ||
| 229 | #define PARSE_ZOFS(p, sym) do { \ | ||
| 230 | if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym))) \ | ||
| 231 | sym = strtoul(p + 11 + sizeof(#sym), NULL, 16); \ | ||
| 232 | } while (0) | ||
| 233 | |||
| 234 | static void parse_zoffset(char *fname) | ||
| 235 | { | ||
| 236 | FILE *file; | ||
| 237 | char *p; | ||
| 238 | int c; | ||
| 239 | |||
| 240 | file = fopen(fname, "r"); | ||
| 241 | if (!file) | ||
| 242 | die("Unable to open `%s': %m", fname); | ||
| 243 | c = fread(buf, 1, sizeof(buf) - 1, file); | ||
| 244 | if (ferror(file)) | ||
| 245 | die("read-error on `zoffset.h'"); | ||
| 246 | buf[c] = 0; | ||
| 247 | |||
| 248 | p = (char *)buf; | ||
| 249 | |||
| 250 | while (p && *p) { | ||
| 251 | PARSE_ZOFS(p, efi_stub_entry); | ||
| 252 | PARSE_ZOFS(p, efi_pe_entry); | ||
| 253 | PARSE_ZOFS(p, startup_64); | ||
| 254 | |||
| 255 | p = strchr(p, '\n'); | ||
| 256 | while (p && (*p == '\r' || *p == '\n')) | ||
| 257 | p++; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 233 | int main(int argc, char ** argv) | 261 | int main(int argc, char ** argv) |
| 234 | { | 262 | { |
| 235 | unsigned int i, sz, setup_sectors; | 263 | unsigned int i, sz, setup_sectors; |
| @@ -241,7 +269,19 @@ int main(int argc, char ** argv) | |||
| 241 | void *kernel; | 269 | void *kernel; |
| 242 | u32 crc = 0xffffffffUL; | 270 | u32 crc = 0xffffffffUL; |
| 243 | 271 | ||
| 244 | if (argc != 3) | 272 | /* Defaults for old kernel */ |
| 273 | #ifdef CONFIG_X86_32 | ||
| 274 | efi_pe_entry = 0x10; | ||
| 275 | efi_stub_entry = 0x30; | ||
| 276 | #else | ||
| 277 | efi_pe_entry = 0x210; | ||
| 278 | efi_stub_entry = 0x230; | ||
| 279 | startup_64 = 0x200; | ||
| 280 | #endif | ||
| 281 | |||
| 282 | if (argc == 4) | ||
| 283 | parse_zoffset(argv[3]); | ||
| 284 | else if (argc != 3) | ||
| 245 | usage(); | 285 | usage(); |
| 246 | 286 | ||
| 247 | /* Copy the setup code */ | 287 | /* Copy the setup code */ |
| @@ -299,6 +339,11 @@ int main(int argc, char ** argv) | |||
| 299 | 339 | ||
| 300 | #ifdef CONFIG_EFI_STUB | 340 | #ifdef CONFIG_EFI_STUB |
| 301 | update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz)); | 341 | update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz)); |
| 342 | |||
| 343 | #ifdef CONFIG_X86_64 /* Yes, this is really how we defined it :( */ | ||
| 344 | efi_stub_entry -= 0x200; | ||
| 345 | #endif | ||
| 346 | put_unaligned_le32(efi_stub_entry, &buf[0x264]); | ||
| 302 | #endif | 347 | #endif |
| 303 | 348 | ||
| 304 | crc = partial_crc32(buf, i, crc); | 349 | crc = partial_crc32(buf, i, crc); |
