mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-13 00:20:06 +00:00
x86, efi stub: Add .reloc section back into image
Some UEFI firmware will not load a .efi with a .reloc section with a size of 0. Therefore, we create a .efi image with 4 main areas and 3 sections. 1. PE/COFF file header 2. .setup section (covers all setup code following the first sector) 3. .reloc section (contains 1 dummy reloc entry, created in build.c) 4. .text section (covers the remaining kernel image) To make room for the new .setup section data, the header bugger_off_msg had to be shortened. Reported-by: Henrik Rydberg <rydberg@euromail.se> Signed-off-by: Jordan Justen <jordan.l.justen@intel.com> Link: http://lkml.kernel.org/r/1339085121-12760-1-git-send-email-jordan.l.justen@intel.com Tested-by: Lee G Rosenbaum <lee.g.rosenbaum@intel.com> Tested-by: Henrik Rydberg <rydberg@euromail.se> Cc: Matt Fleming <matt.fleming@intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
parent
f6175f5bfb
commit
743628e868
@ -94,8 +94,8 @@ bs_die:
|
|||||||
|
|
||||||
.section ".bsdata", "a"
|
.section ".bsdata", "a"
|
||||||
bugger_off_msg:
|
bugger_off_msg:
|
||||||
.ascii "Direct booting from floppy is no longer supported.\r\n"
|
.ascii "Direct floppy boot is not supported. "
|
||||||
.ascii "Please use a boot loader program instead.\r\n"
|
.ascii "Use a boot loader program instead.\r\n"
|
||||||
.ascii "\n"
|
.ascii "\n"
|
||||||
.ascii "Remove disk and press any key to reboot ...\r\n"
|
.ascii "Remove disk and press any key to reboot ...\r\n"
|
||||||
.byte 0
|
.byte 0
|
||||||
@ -111,7 +111,7 @@ coff_header:
|
|||||||
#else
|
#else
|
||||||
.word 0x8664 # x86-64
|
.word 0x8664 # x86-64
|
||||||
#endif
|
#endif
|
||||||
.word 2 # nr_sections
|
.word 3 # nr_sections
|
||||||
.long 0 # TimeDateStamp
|
.long 0 # TimeDateStamp
|
||||||
.long 0 # PointerToSymbolTable
|
.long 0 # PointerToSymbolTable
|
||||||
.long 1 # NumberOfSymbols
|
.long 1 # NumberOfSymbols
|
||||||
@ -158,8 +158,8 @@ extra_header_fields:
|
|||||||
#else
|
#else
|
||||||
.quad 0 # ImageBase
|
.quad 0 # ImageBase
|
||||||
#endif
|
#endif
|
||||||
.long 0x1000 # SectionAlignment
|
.long 0x20 # SectionAlignment
|
||||||
.long 0x200 # FileAlignment
|
.long 0x20 # FileAlignment
|
||||||
.word 0 # MajorOperatingSystemVersion
|
.word 0 # MajorOperatingSystemVersion
|
||||||
.word 0 # MinorOperatingSystemVersion
|
.word 0 # MinorOperatingSystemVersion
|
||||||
.word 0 # MajorImageVersion
|
.word 0 # MajorImageVersion
|
||||||
@ -200,8 +200,10 @@ extra_header_fields:
|
|||||||
|
|
||||||
# Section table
|
# Section table
|
||||||
section_table:
|
section_table:
|
||||||
.ascii ".text"
|
#
|
||||||
.byte 0
|
# The offset & size fields are filled in by build.c.
|
||||||
|
#
|
||||||
|
.ascii ".setup"
|
||||||
.byte 0
|
.byte 0
|
||||||
.byte 0
|
.byte 0
|
||||||
.long 0
|
.long 0
|
||||||
@ -217,9 +219,8 @@ section_table:
|
|||||||
|
|
||||||
#
|
#
|
||||||
# The EFI application loader requires a relocation section
|
# The EFI application loader requires a relocation section
|
||||||
# because EFI applications must be relocatable. But since
|
# because EFI applications must be relocatable. The .reloc
|
||||||
# we don't need the loader to fixup any relocs for us, we
|
# offset & size fields are filled in by build.c.
|
||||||
# just create an empty (zero-length) .reloc section header.
|
|
||||||
#
|
#
|
||||||
.ascii ".reloc"
|
.ascii ".reloc"
|
||||||
.byte 0
|
.byte 0
|
||||||
@ -233,6 +234,25 @@ section_table:
|
|||||||
.word 0 # NumberOfRelocations
|
.word 0 # NumberOfRelocations
|
||||||
.word 0 # NumberOfLineNumbers
|
.word 0 # NumberOfLineNumbers
|
||||||
.long 0x42100040 # Characteristics (section flags)
|
.long 0x42100040 # Characteristics (section flags)
|
||||||
|
|
||||||
|
#
|
||||||
|
# The offset & size fields are filled in by build.c.
|
||||||
|
#
|
||||||
|
.ascii ".text"
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.long 0
|
||||||
|
.long 0x0 # startup_{32,64}
|
||||||
|
.long 0 # Size of initialized data
|
||||||
|
# on disk
|
||||||
|
.long 0x0 # startup_{32,64}
|
||||||
|
.long 0 # PointerToRelocations
|
||||||
|
.long 0 # PointerToLineNumbers
|
||||||
|
.word 0 # NumberOfRelocations
|
||||||
|
.word 0 # NumberOfLineNumbers
|
||||||
|
.long 0x60500020 # Characteristics (section flags)
|
||||||
|
|
||||||
#endif /* CONFIG_EFI_STUB */
|
#endif /* CONFIG_EFI_STUB */
|
||||||
|
|
||||||
# Kernel attributes; used by setup. This is part 1 of the
|
# Kernel attributes; used by setup. This is part 1 of the
|
||||||
|
@ -50,6 +50,8 @@ typedef unsigned int u32;
|
|||||||
u8 buf[SETUP_SECT_MAX*512];
|
u8 buf[SETUP_SECT_MAX*512];
|
||||||
int is_big_kernel;
|
int is_big_kernel;
|
||||||
|
|
||||||
|
#define PECOFF_RELOC_RESERVE 0x20
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static const u32 crctab32[] = {
|
static const u32 crctab32[] = {
|
||||||
@ -133,11 +135,103 @@ static void usage(void)
|
|||||||
die("Usage: build setup system [> image]");
|
die("Usage: build setup system [> image]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_EFI_STUB
|
||||||
|
|
||||||
|
static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
|
||||||
|
{
|
||||||
|
unsigned int pe_header;
|
||||||
|
unsigned short num_sections;
|
||||||
|
u8 *section;
|
||||||
|
|
||||||
|
pe_header = get_unaligned_le32(&buf[0x3c]);
|
||||||
|
num_sections = get_unaligned_le16(&buf[pe_header + 6]);
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
|
section = &buf[pe_header + 0xa8];
|
||||||
|
#else
|
||||||
|
section = &buf[pe_header + 0xb8];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (num_sections > 0) {
|
||||||
|
if (strncmp((char*)section, section_name, 8) == 0) {
|
||||||
|
/* section header size field */
|
||||||
|
put_unaligned_le32(size, section + 0x8);
|
||||||
|
|
||||||
|
/* section header vma field */
|
||||||
|
put_unaligned_le32(offset, section + 0xc);
|
||||||
|
|
||||||
|
/* section header 'size of initialised data' field */
|
||||||
|
put_unaligned_le32(size, section + 0x10);
|
||||||
|
|
||||||
|
/* section header 'file offset' field */
|
||||||
|
put_unaligned_le32(offset, section + 0x14);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
section += 0x28;
|
||||||
|
num_sections--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_pecoff_setup_and_reloc(unsigned int size)
|
||||||
|
{
|
||||||
|
u32 setup_offset = 0x200;
|
||||||
|
u32 reloc_offset = size - PECOFF_RELOC_RESERVE;
|
||||||
|
u32 setup_size = reloc_offset - setup_offset;
|
||||||
|
|
||||||
|
update_pecoff_section_header(".setup", setup_offset, setup_size);
|
||||||
|
update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modify .reloc section contents with a single entry. The
|
||||||
|
* relocation is applied to offset 10 of the relocation section.
|
||||||
|
*/
|
||||||
|
put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
|
||||||
|
put_unaligned_le32(10, &buf[reloc_offset + 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
|
||||||
|
{
|
||||||
|
unsigned int pe_header;
|
||||||
|
unsigned int text_sz = file_sz - text_start;
|
||||||
|
|
||||||
|
pe_header = get_unaligned_le32(&buf[0x3c]);
|
||||||
|
|
||||||
|
/* Size of image */
|
||||||
|
put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of code: Subtract the size of the first sector (512 bytes)
|
||||||
|
* which includes the header.
|
||||||
|
*/
|
||||||
|
put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
|
/*
|
||||||
|
* Address of entry point.
|
||||||
|
*
|
||||||
|
* The EFI stub entry point is +16 bytes from the start of
|
||||||
|
* the .text section.
|
||||||
|
*/
|
||||||
|
put_unaligned_le32(text_start + 16, &buf[pe_header + 0x28]);
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* Address of entry point. startup_32 is at the beginning and
|
||||||
|
* the 64-bit entry point (startup_64) is always 512 bytes
|
||||||
|
* after. The EFI stub entry point is 16 bytes after that, as
|
||||||
|
* the first instruction allows legacy loaders to jump over
|
||||||
|
* the EFI stub initialisation
|
||||||
|
*/
|
||||||
|
put_unaligned_le32(text_start + 528, &buf[pe_header + 0x28]);
|
||||||
|
#endif /* CONFIG_X86_32 */
|
||||||
|
|
||||||
|
update_pecoff_section_header(".text", text_start, text_sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_EFI_STUB */
|
||||||
|
|
||||||
int main(int argc, char ** argv)
|
int main(int argc, char ** argv)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_EFI_STUB
|
|
||||||
unsigned int file_sz, pe_header;
|
|
||||||
#endif
|
|
||||||
unsigned int i, sz, setup_sectors;
|
unsigned int i, sz, setup_sectors;
|
||||||
int c;
|
int c;
|
||||||
u32 sys_size;
|
u32 sys_size;
|
||||||
@ -163,6 +257,12 @@ int main(int argc, char ** argv)
|
|||||||
die("Boot block hasn't got boot flag (0xAA55)");
|
die("Boot block hasn't got boot flag (0xAA55)");
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
|
#ifdef CONFIG_EFI_STUB
|
||||||
|
/* Reserve 0x20 bytes for .reloc section */
|
||||||
|
memset(buf+c, 0, PECOFF_RELOC_RESERVE);
|
||||||
|
c += PECOFF_RELOC_RESERVE;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Pad unused space with zeros */
|
/* Pad unused space with zeros */
|
||||||
setup_sectors = (c + 511) / 512;
|
setup_sectors = (c + 511) / 512;
|
||||||
if (setup_sectors < SETUP_SECT_MIN)
|
if (setup_sectors < SETUP_SECT_MIN)
|
||||||
@ -170,6 +270,10 @@ int main(int argc, char ** argv)
|
|||||||
i = setup_sectors*512;
|
i = setup_sectors*512;
|
||||||
memset(buf+c, 0, i-c);
|
memset(buf+c, 0, i-c);
|
||||||
|
|
||||||
|
#ifdef CONFIG_EFI_STUB
|
||||||
|
update_pecoff_setup_and_reloc(i);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set the default root device */
|
/* Set the default root device */
|
||||||
put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
|
put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
|
||||||
|
|
||||||
@ -194,66 +298,8 @@ int main(int argc, char ** argv)
|
|||||||
put_unaligned_le32(sys_size, &buf[0x1f4]);
|
put_unaligned_le32(sys_size, &buf[0x1f4]);
|
||||||
|
|
||||||
#ifdef CONFIG_EFI_STUB
|
#ifdef CONFIG_EFI_STUB
|
||||||
file_sz = sz + i + ((sys_size * 16) - sz);
|
update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz));
|
||||||
|
#endif
|
||||||
pe_header = get_unaligned_le32(&buf[0x3c]);
|
|
||||||
|
|
||||||
/* Size of image */
|
|
||||||
put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Subtract the size of the first section (512 bytes) which
|
|
||||||
* includes the header and .reloc section. The remaining size
|
|
||||||
* is that of the .text section.
|
|
||||||
*/
|
|
||||||
file_sz -= 512;
|
|
||||||
|
|
||||||
/* Size of code */
|
|
||||||
put_unaligned_le32(file_sz, &buf[pe_header + 0x1c]);
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
/*
|
|
||||||
* Address of entry point.
|
|
||||||
*
|
|
||||||
* The EFI stub entry point is +16 bytes from the start of
|
|
||||||
* the .text section.
|
|
||||||
*/
|
|
||||||
put_unaligned_le32(i + 16, &buf[pe_header + 0x28]);
|
|
||||||
|
|
||||||
/* .text size */
|
|
||||||
put_unaligned_le32(file_sz, &buf[pe_header + 0xb0]);
|
|
||||||
|
|
||||||
/* .text vma */
|
|
||||||
put_unaligned_le32(0x200, &buf[pe_header + 0xb4]);
|
|
||||||
|
|
||||||
/* .text size of initialised data */
|
|
||||||
put_unaligned_le32(file_sz, &buf[pe_header + 0xb8]);
|
|
||||||
|
|
||||||
/* .text file offset */
|
|
||||||
put_unaligned_le32(0x200, &buf[pe_header + 0xbc]);
|
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* Address of entry point. startup_32 is at the beginning and
|
|
||||||
* the 64-bit entry point (startup_64) is always 512 bytes
|
|
||||||
* after. The EFI stub entry point is 16 bytes after that, as
|
|
||||||
* the first instruction allows legacy loaders to jump over
|
|
||||||
* the EFI stub initialisation
|
|
||||||
*/
|
|
||||||
put_unaligned_le32(i + 528, &buf[pe_header + 0x28]);
|
|
||||||
|
|
||||||
/* .text size */
|
|
||||||
put_unaligned_le32(file_sz, &buf[pe_header + 0xc0]);
|
|
||||||
|
|
||||||
/* .text vma */
|
|
||||||
put_unaligned_le32(0x200, &buf[pe_header + 0xc4]);
|
|
||||||
|
|
||||||
/* .text size of initialised data */
|
|
||||||
put_unaligned_le32(file_sz, &buf[pe_header + 0xc8]);
|
|
||||||
|
|
||||||
/* .text file offset */
|
|
||||||
put_unaligned_le32(0x200, &buf[pe_header + 0xcc]);
|
|
||||||
#endif /* CONFIG_X86_32 */
|
|
||||||
#endif /* CONFIG_EFI_STUB */
|
|
||||||
|
|
||||||
crc = partial_crc32(buf, i, crc);
|
crc = partial_crc32(buf, i, crc);
|
||||||
if (fwrite(buf, 1, i, stdout) != i)
|
if (fwrite(buf, 1, i, stdout) != i)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user