diff options
| -rw-r--r-- | arch/x86/boot/Makefile | 4 | ||||
| -rw-r--r-- | arch/x86/boot/compressed/head_32.S | 6 | ||||
| -rw-r--r-- | arch/x86/boot/compressed/head_64.S | 8 | ||||
| -rw-r--r-- | arch/x86/boot/tools/build.c | 81 |
4 files changed, 72 insertions, 27 deletions
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index ccce0ed67dde..379814bc41e3 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile | |||
| @@ -71,7 +71,7 @@ GCOV_PROFILE := n | |||
| 71 | $(obj)/bzImage: asflags-y := $(SVGA_MODE) | 71 | $(obj)/bzImage: asflags-y := $(SVGA_MODE) |
| 72 | 72 | ||
| 73 | quiet_cmd_image = BUILD $@ | 73 | quiet_cmd_image = BUILD $@ |
| 74 | cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin > $@ | 74 | cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/zoffset.h > $@ |
| 75 | 75 | ||
| 76 | $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE | 76 | $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE |
| 77 | $(call if_changed,image) | 77 | $(call if_changed,image) |
| @@ -92,7 +92,7 @@ targets += voffset.h | |||
| 92 | $(obj)/voffset.h: vmlinux FORCE | 92 | $(obj)/voffset.h: vmlinux FORCE |
| 93 | $(call if_changed,voffset) | 93 | $(call if_changed,voffset) |
| 94 | 94 | ||
| 95 | sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p' | 95 | sed-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' |
| 96 | 96 | ||
| 97 | quiet_cmd_zoffset = ZOFFSET $@ | 97 | quiet_cmd_zoffset = ZOFFSET $@ |
| 98 | cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@ | 98 | cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@ |
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index ccb2f4a5f7bd..1e3184f6072f 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S | |||
| @@ -35,11 +35,11 @@ ENTRY(startup_32) | |||
| 35 | #ifdef CONFIG_EFI_STUB | 35 | #ifdef CONFIG_EFI_STUB |
| 36 | jmp preferred_addr | 36 | jmp preferred_addr |
| 37 | 37 | ||
| 38 | .balign 0x10 | ||
| 39 | /* | 38 | /* |
| 40 | * We don't need the return address, so set up the stack so | 39 | * We don't need the return address, so set up the stack so |
| 41 | * efi_main() can find its arugments. | 40 | * efi_main() can find its arguments. |
| 42 | */ | 41 | */ |
| 42 | ENTRY(efi_pe_entry) | ||
| 43 | add $0x4, %esp | 43 | add $0x4, %esp |
| 44 | 44 | ||
| 45 | call make_boot_params | 45 | call make_boot_params |
| @@ -52,7 +52,7 @@ ENTRY(startup_32) | |||
| 52 | pushl %ecx | 52 | pushl %ecx |
| 53 | sub $0x4, %esp | 53 | sub $0x4, %esp |
| 54 | 54 | ||
| 55 | .org 0x30,0x90 | 55 | ENTRY(efi_stub_entry) |
| 56 | add $0x4, %esp | 56 | add $0x4, %esp |
| 57 | call efi_main | 57 | call efi_main |
| 58 | cmpl $0, %eax | 58 | cmpl $0, %eax |
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 2c4b171eec33..f5d1aaa0dec8 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S | |||
| @@ -201,12 +201,12 @@ ENTRY(startup_64) | |||
| 201 | */ | 201 | */ |
| 202 | #ifdef CONFIG_EFI_STUB | 202 | #ifdef CONFIG_EFI_STUB |
| 203 | /* | 203 | /* |
| 204 | * The entry point for the PE/COFF executable is 0x210, so only | 204 | * The entry point for the PE/COFF executable is efi_pe_entry, so |
| 205 | * legacy boot loaders will execute this jmp. | 205 | * only legacy boot loaders will execute this jmp. |
| 206 | */ | 206 | */ |
| 207 | jmp preferred_addr | 207 | jmp preferred_addr |
| 208 | 208 | ||
| 209 | .org 0x210 | 209 | ENTRY(efi_pe_entry) |
| 210 | mov %rcx, %rdi | 210 | mov %rcx, %rdi |
| 211 | mov %rdx, %rsi | 211 | mov %rdx, %rsi |
| 212 | pushq %rdi | 212 | pushq %rdi |
| @@ -218,7 +218,7 @@ ENTRY(startup_64) | |||
| 218 | popq %rsi | 218 | popq %rsi |
| 219 | popq %rdi | 219 | popq %rdi |
| 220 | 220 | ||
| 221 | .org 0x230,0x90 | 221 | ENTRY(efi_stub_entry) |
| 222 | call efi_main | 222 | call efi_main |
| 223 | movq %rax,%rsi | 223 | movq %rax,%rsi |
| 224 | cmpq $0,%rax | 224 | cmpq $0,%rax |
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); |
