Skip to content

Commit fd06f5d

Browse files
Pingfan LiuKernel Patches Daemon
authored andcommitted
tools/kexec: Add a zboot image building tool
The objcopy binary can append an section into PE file, but it disregards the DOS header. While the zboot format carries important information: payload offset and size in the DOS header. In order to keep track and update such information, here introducing a dedicated binary tool to build zboot image. The payload offset is determined by the fact that its offset inside the .data section is unchanged. Hence the offset of .data section in the new PE file plus the payload offset within section renders the offset within the new PE file. The objcopy binary can append a section to a PE file, but it disregards the DOS header. However, the zboot format carries important information in the DOS header: payload offset and size. To track this information and append a new PE section, here a dedicated binary tool is introduced to build zboot images. The payload's relative offset within the .data section remains unchanged. Therefore, the .data section offset in the new PE file, plus the payload offset within that section, yields the payload offset within the new PE file. Finally, the new PE file 'zboot.efi' can be got by the command: make -C tools/kexec zboot Signed-off-by: Pingfan Liu <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Baoquan He <[email protected]> Cc: Dave Young <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Philipp Rudo <[email protected]> Cc: [email protected] To: [email protected]
1 parent ddb0dba commit fd06f5d

File tree

3 files changed

+466
-1
lines changed

3 files changed

+466
-1
lines changed

tools/kexec/Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ BPFTOOL = bpftool
2727

2828
# List of generated target files
2929
HEADERS = vmlinux.h bpf_helper_defs.h image_size.h
30-
ZBOOT_TARGETS = bytecode.c zboot_parser_bpf.o bytecode.o
30+
ZBOOT_TARGETS = bytecode.c zboot_parser_bpf.o bytecode.o zboot_image_builder zboot.efi
3131

3232

3333
# Targets
@@ -75,6 +75,14 @@ bytecode.c: zboot_parser_bpf.o
7575
bytecode.o: bytecode.c
7676
@$(CC) -c $< -o $@
7777

78+
# Rule to build zboot_image_builder executable
79+
zboot_image_builder: zboot_image_builder.c
80+
@$(CC) $(CFLAGS) $< -o $@
81+
82+
zboot.efi: zboot_image_builder bytecode.o
83+
@chmod +x zboot_image_builder
84+
@./zboot_image_builder $(EFI_IMAGE) bytecode.o $@
85+
7886
# Clean up generated files
7987
clean:
8088
@rm -f $(HEADERS) $(ZBOOT_TARGETS)

tools/kexec/pe.h

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* Extract from linux kernel include/linux/pe.h
3+
*/
4+
5+
#ifndef __PE_H__
6+
#define __PE_H__
7+
8+
#define IMAGE_DOS_SIGNATURE 0x5a4d /* "MZ" */
9+
#define IMAGE_NT_SIGNATURE 0x00004550 /* "PE\0\0" */
10+
11+
struct mz_hdr {
12+
uint16_t magic; /* MZ_MAGIC */
13+
uint16_t lbsize; /* size of last used block */
14+
uint16_t blocks; /* pages in file, 0x3 */
15+
uint16_t relocs; /* relocations */
16+
uint16_t hdrsize; /* header size in "paragraphs" */
17+
uint16_t min_extra_pps; /* .bss */
18+
uint16_t max_extra_pps; /* runtime limit for the arena size */
19+
uint16_t ss; /* relative stack segment */
20+
uint16_t sp; /* initial %sp register */
21+
uint16_t checksum; /* word checksum */
22+
uint16_t ip; /* initial %ip register */
23+
uint16_t cs; /* initial %cs relative to load segment */
24+
uint16_t reloc_table_offset; /* offset of the first relocation */
25+
uint16_t overlay_num; /* overlay number. set to 0. */
26+
uint16_t reserved0[4]; /* reserved */
27+
uint16_t oem_id; /* oem identifier */
28+
uint16_t oem_info; /* oem specific */
29+
uint16_t reserved1[10]; /* reserved */
30+
uint32_t peaddr; /* address of pe header */
31+
char message[]; /* message to print */
32+
};
33+
34+
struct pe_hdr {
35+
uint32_t magic; /* PE magic */
36+
uint16_t machine; /* machine type */
37+
uint16_t sections; /* number of sections */
38+
uint32_t timestamp; /* time_t */
39+
uint32_t symbol_table; /* symbol table offset */
40+
uint32_t symbols; /* number of symbols */
41+
uint16_t opt_hdr_size; /* size of optional header */
42+
uint16_t flags; /* flags */
43+
};
44+
45+
/* the fact that pe32 isn't padded where pe32+ is 64-bit means union won't
46+
* work right. vomit. */
47+
struct pe32_opt_hdr {
48+
/* "standard" header */
49+
uint16_t magic; /* file type */
50+
uint8_t ld_major; /* linker major version */
51+
uint8_t ld_minor; /* linker minor version */
52+
uint32_t text_size; /* size of text section(s) */
53+
uint32_t data_size; /* size of data section(s) */
54+
uint32_t bss_size; /* size of bss section(s) */
55+
uint32_t entry_point; /* file offset of entry point */
56+
uint32_t code_base; /* relative code addr in ram */
57+
uint32_t data_base; /* relative data addr in ram */
58+
/* "windows" header */
59+
uint32_t image_base; /* preferred load address */
60+
uint32_t section_align; /* alignment in bytes */
61+
uint32_t file_align; /* file alignment in bytes */
62+
uint16_t os_major; /* major OS version */
63+
uint16_t os_minor; /* minor OS version */
64+
uint16_t image_major; /* major image version */
65+
uint16_t image_minor; /* minor image version */
66+
uint16_t subsys_major; /* major subsystem version */
67+
uint16_t subsys_minor; /* minor subsystem version */
68+
uint32_t win32_version; /* reserved, must be 0 */
69+
uint32_t image_size; /* image size */
70+
uint32_t header_size; /* header size rounded up to
71+
file_align */
72+
uint32_t csum; /* checksum */
73+
uint16_t subsys; /* subsystem */
74+
uint16_t dll_flags; /* more flags! */
75+
uint32_t stack_size_req;/* amt of stack requested */
76+
uint32_t stack_size; /* amt of stack required */
77+
uint32_t heap_size_req; /* amt of heap requested */
78+
uint32_t heap_size; /* amt of heap required */
79+
uint32_t loader_flags; /* reserved, must be 0 */
80+
uint32_t data_dirs; /* number of data dir entries */
81+
};
82+
83+
struct pe32plus_opt_hdr {
84+
uint16_t magic; /* file type */
85+
uint8_t ld_major; /* linker major version */
86+
uint8_t ld_minor; /* linker minor version */
87+
uint32_t text_size; /* size of text section(s) */
88+
uint32_t data_size; /* size of data section(s) */
89+
uint32_t bss_size; /* size of bss section(s) */
90+
uint32_t entry_point; /* file offset of entry point */
91+
uint32_t code_base; /* relative code addr in ram */
92+
/* "windows" header */
93+
uint64_t image_base; /* preferred load address */
94+
uint32_t section_align; /* alignment in bytes */
95+
uint32_t file_align; /* file alignment in bytes */
96+
uint16_t os_major; /* major OS version */
97+
uint16_t os_minor; /* minor OS version */
98+
uint16_t image_major; /* major image version */
99+
uint16_t image_minor; /* minor image version */
100+
uint16_t subsys_major; /* major subsystem version */
101+
uint16_t subsys_minor; /* minor subsystem version */
102+
uint32_t win32_version; /* reserved, must be 0 */
103+
uint32_t image_size; /* image size */
104+
uint32_t header_size; /* header size rounded up to
105+
file_align */
106+
uint32_t csum; /* checksum */
107+
uint16_t subsys; /* subsystem */
108+
uint16_t dll_flags; /* more flags! */
109+
uint64_t stack_size_req;/* amt of stack requested */
110+
uint64_t stack_size; /* amt of stack required */
111+
uint64_t heap_size_req; /* amt of heap requested */
112+
uint64_t heap_size; /* amt of heap required */
113+
uint32_t loader_flags; /* reserved, must be 0 */
114+
uint32_t data_dirs; /* number of data dir entries */
115+
};
116+
117+
struct data_dirent {
118+
uint32_t virtual_address; /* relative to load address */
119+
uint32_t size;
120+
};
121+
122+
struct data_directory {
123+
struct data_dirent exports; /* .edata */
124+
struct data_dirent imports; /* .idata */
125+
struct data_dirent resources; /* .rsrc */
126+
struct data_dirent exceptions; /* .pdata */
127+
struct data_dirent certs; /* certs */
128+
struct data_dirent base_relocations; /* .reloc */
129+
struct data_dirent debug; /* .debug */
130+
struct data_dirent arch; /* reservered */
131+
struct data_dirent global_ptr; /* global pointer reg. Size=0 */
132+
struct data_dirent tls; /* .tls */
133+
struct data_dirent load_config; /* load configuration structure */
134+
struct data_dirent bound_imports; /* no idea */
135+
struct data_dirent import_addrs; /* import address table */
136+
struct data_dirent delay_imports; /* delay-load import table */
137+
struct data_dirent clr_runtime_hdr; /* .cor (object only) */
138+
struct data_dirent reserved;
139+
};
140+
141+
struct section_header {
142+
char name[8]; /* name or "/12\0" string tbl offset */
143+
uint32_t virtual_size; /* size of loaded section in ram */
144+
uint32_t virtual_address; /* relative virtual address */
145+
uint32_t raw_data_size; /* size of the section */
146+
uint32_t data_addr; /* file pointer to first page of sec */
147+
uint32_t relocs; /* file pointer to relocation entries */
148+
uint32_t line_numbers; /* line numbers! */
149+
uint16_t num_relocs; /* number of relocations */
150+
uint16_t num_lin_numbers; /* srsly. */
151+
uint32_t flags;
152+
};
153+
154+
struct win_certificate {
155+
uint32_t length;
156+
uint16_t revision;
157+
uint16_t cert_type;
158+
};
159+
160+
/*
161+
* Return -1 if not PE, else offset of the PE header
162+
*/
163+
static int get_pehdr_offset(const char *buf)
164+
{
165+
int pe_hdr_offset;
166+
167+
pe_hdr_offset = *((int *)(buf + 0x3c));
168+
buf += pe_hdr_offset;
169+
if (!!memcmp(buf, "PE\0\0", 4)) {
170+
printf("Not a PE file\n");
171+
return -1;
172+
}
173+
174+
return pe_hdr_offset;
175+
}
176+
177+
#endif

0 commit comments

Comments
 (0)