[U-Boot] [PATCH 03/14] efi_loader: Add PE image loader

Alexander Graf agraf at suse.de
Mon Feb 1 23:58:54 CET 2016



On 01/31/2016 04:18 PM, Simon Glass wrote:
> Hi Alexander,
>
> On 14 January 2016 at 22:06, Alexander Graf <agraf at suse.de> wrote:
>> EFI uses the PE binary format for its application images. Add support to EFI PE
>> binaries as well as all necessary bits for the "EFI image loader" interfaces.
>>
>> Signed-off-by: Alexander Graf <agraf at suse.de>
>>
>> ---
>>
>> v1 -> v2:
>>
>>    - move memory allocation to separate patch
>>    - limit 32/64 to hosts that support it
>>    - check 32bit optional nt header magic
>>    - switch to GPL2+
>> ---
>>   include/efi_loader.h              |  23 ++++
>>   include/pe.h                      | 263 ++++++++++++++++++++++++++++++++++++++
>>   lib/efi_loader/efi_image_loader.c | 178 ++++++++++++++++++++++++++
>>   3 files changed, 464 insertions(+)
>>   create mode 100644 include/efi_loader.h
>>   create mode 100644 include/pe.h
>>   create mode 100644 lib/efi_loader/efi_image_loader.c
>>
>> diff --git a/include/efi_loader.h b/include/efi_loader.h
>> new file mode 100644
>> index 0000000..bf77573
>> --- /dev/null
>> +++ b/include/efi_loader.h
>> @@ -0,0 +1,23 @@
>> +/*
>> + *  EFI application loader
>> + *
>> + *  Copyright (c) 2016 Alexander Graf
>> + *
>> + *  SPDX-License-Identifier:     GPL-2.0+
>> + */
>> +
>> +#include <part_efi.h>
>> +#include <efi_api.h>
>> +#include <linux/list.h>
>> +
>> +extern const efi_guid_t efi_guid_device_path;
>> +extern const efi_guid_t efi_guid_loaded_image;
>> +
>> +efi_status_t efi_return_handle(void *handle,
>> +               efi_guid_t *protocol, void **protocol_interface,
>> +               void *agent_handle, void *controller_handle,
>> +               uint32_t attributes);
>> +void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info);
>> +
>> +#define EFI_LOADER_POOL_SIZE (128 * 1024 * 1024)
>> +void *efi_loader_alloc(uint64_t len);
>> diff --git a/include/pe.h b/include/pe.h
>> new file mode 100644
>> index 0000000..6379ae1
>> --- /dev/null
>> +++ b/include/pe.h
>> @@ -0,0 +1,263 @@
>> +/*
>> + *  Portable Executable binary format structures
>> + *
>> + *  Copyright (c) 2016 Alexander Graf
>> + *
>> + *  Based on wine code
>> + *
>> + *  SPDX-License-Identifier:     GPL-2.0+
>> + */
>> +
>> +#ifndef _PE_H
>> +#define _PE_H
>> +
>> +typedef struct _IMAGE_DOS_HEADER {
>> +       uint16_t e_magic;      /* 00: MZ Header signature */
>> +       uint16_t e_cblp;       /* 02: Bytes on last page of file */
>> +       uint16_t e_cp;         /* 04: Pages in file */
>> +       uint16_t e_crlc;       /* 06: Relocations */
>> +       uint16_t e_cparhdr;    /* 08: Size of header in paragraphs */
>> +       uint16_t e_minalloc;   /* 0a: Minimum extra paragraphs needed */
>> +       uint16_t e_maxalloc;   /* 0c: Maximum extra paragraphs needed */
>> +       uint16_t e_ss;         /* 0e: Initial (relative) SS value */
>> +       uint16_t e_sp;         /* 10: Initial SP value */
>> +       uint16_t e_csum;       /* 12: Checksum */
>> +       uint16_t e_ip;         /* 14: Initial IP value */
>> +       uint16_t e_cs;         /* 16: Initial (relative) CS value */
>> +       uint16_t e_lfarlc;     /* 18: File address of relocation table */
>> +       uint16_t e_ovno;       /* 1a: Overlay number */
>> +       uint16_t e_res[4];     /* 1c: Reserved words */
>> +       uint16_t e_oemid;      /* 24: OEM identifier (for e_oeminfo) */
>> +       uint16_t e_oeminfo;    /* 26: OEM information; e_oemid specific */
>> +       uint16_t e_res2[10];   /* 28: Reserved words */
>> +       uint32_t e_lfanew;     /* 3c: Offset to extended header */
>> +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
>> +
>> +#define IMAGE_DOS_SIGNATURE            0x5A4D     /* MZ   */
>> +#define IMAGE_NT_SIGNATURE             0x00004550 /* PE00 */
>> +
>> +#define IMAGE_FILE_MACHINE_ARM         0x01c0
>> +#define IMAGE_FILE_MACHINE_THUMB       0x01c2
>> +#define IMAGE_FILE_MACHINE_ARMNT       0x01c4
>> +#define IMAGE_FILE_MACHINE_AMD64       0x8664
>> +#define IMAGE_FILE_MACHINE_ARM64       0xaa64
>> +#define IMAGE_NT_OPTIONAL_HDR32_MAGIC  0x10b
>> +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC  0x20b
>> +#define IMAGE_SUBSYSTEM_EFI_APPLICATION        10
>> +
>> +typedef struct _IMAGE_FILE_HEADER {
>> +       uint16_t  Machine;
>> +       uint16_t  NumberOfSections;
>> +       uint32_t TimeDateStamp;
>> +       uint32_t PointerToSymbolTable;
>> +       uint32_t NumberOfSymbols;
>> +       uint16_t  SizeOfOptionalHeader;
>> +       uint16_t  Characteristics;
>> +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
>> +
>> +typedef struct _IMAGE_DATA_DIRECTORY {
>> +       uint32_t VirtualAddress;
>> +       uint32_t Size;
>> +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
>> +
>> +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
>> +
>> +typedef struct _IMAGE_OPTIONAL_HEADER64 {
>> +       uint16_t  Magic; /* 0x20b */
>> +       uint8_t MajorLinkerVersion;
>> +       uint8_t MinorLinkerVersion;
>> +       uint32_t SizeOfCode;
>> +       uint32_t SizeOfInitializedData;
>> +       uint32_t SizeOfUninitializedData;
>> +       uint32_t AddressOfEntryPoint;
>> +       uint32_t BaseOfCode;
>> +       uint64_t ImageBase;
>> +       uint32_t SectionAlignment;
>> +       uint32_t FileAlignment;
>> +       uint16_t MajorOperatingSystemVersion;
>> +       uint16_t MinorOperatingSystemVersion;
>> +       uint16_t MajorImageVersion;
>> +       uint16_t MinorImageVersion;
>> +       uint16_t MajorSubsystemVersion;
>> +       uint16_t MinorSubsystemVersion;
>> +       uint32_t Win32VersionValue;
>> +       uint32_t SizeOfImage;
>> +       uint32_t SizeOfHeaders;
>> +       uint32_t CheckSum;
>> +       uint16_t Subsystem;
>> +       uint16_t DllCharacteristics;
>> +       uint64_t SizeOfStackReserve;
>> +       uint64_t SizeOfStackCommit;
>> +       uint64_t SizeOfHeapReserve;
>> +       uint64_t SizeOfHeapCommit;
>> +       uint32_t LoaderFlags;
>> +       uint32_t NumberOfRvaAndSizes;
>> +       IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
>> +} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
>> +
>> +typedef struct _IMAGE_NT_HEADERS64 {
>> +       uint32_t Signature;
>> +       IMAGE_FILE_HEADER FileHeader;
>> +       IMAGE_OPTIONAL_HEADER64 OptionalHeader;
>> +} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
>> +
>> +typedef struct _IMAGE_OPTIONAL_HEADER {
>> +
>> +       /* Standard fields */
>> +
>> +       uint16_t  Magic; /* 0x10b or 0x107 */     /* 0x00 */
>> +       uint8_t  MajorLinkerVersion;
>> +       uint8_t  MinorLinkerVersion;
>> +       uint32_t SizeOfCode;
>> +       uint32_t SizeOfInitializedData;
>> +       uint32_t SizeOfUninitializedData;
>> +       uint32_t AddressOfEntryPoint;            /* 0x10 */
>> +       uint32_t BaseOfCode;
>> +       uint32_t BaseOfData;
>> +
>> +       /* NT additional fields */
>> +
>> +       uint32_t ImageBase;
>> +       uint32_t SectionAlignment;               /* 0x20 */
>> +       uint32_t FileAlignment;
>> +       uint16_t  MajorOperatingSystemVersion;
>> +       uint16_t  MinorOperatingSystemVersion;
>> +       uint16_t  MajorImageVersion;
>> +       uint16_t  MinorImageVersion;
>> +       uint16_t  MajorSubsystemVersion;          /* 0x30 */
>> +       uint16_t  MinorSubsystemVersion;
>> +       uint32_t Win32VersionValue;
>> +       uint32_t SizeOfImage;
>> +       uint32_t SizeOfHeaders;
>> +       uint32_t CheckSum;                       /* 0x40 */
>> +       uint16_t  Subsystem;
>> +       uint16_t  DllCharacteristics;
>> +       uint32_t SizeOfStackReserve;
>> +       uint32_t SizeOfStackCommit;
>> +       uint32_t SizeOfHeapReserve;              /* 0x50 */
>> +       uint32_t SizeOfHeapCommit;
>> +       uint32_t LoaderFlags;
>> +       uint32_t NumberOfRvaAndSizes;
>> +       IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; /* 0x60 */
>> +       /* 0xE0 */
>> +} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
>> +
>> +typedef struct _IMAGE_NT_HEADERS {
>> +       uint32_t Signature; /* "PE"\0\0 */       /* 0x00 */
>> +       IMAGE_FILE_HEADER FileHeader;         /* 0x04 */
>> +       IMAGE_OPTIONAL_HEADER32 OptionalHeader;       /* 0x18 */
>> +} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
>> +
>> +#define IMAGE_SIZEOF_SHORT_NAME 8
>> +
>> +typedef struct _IMAGE_SECTION_HEADER {
>> +       uint8_t Name[IMAGE_SIZEOF_SHORT_NAME];
>> +       union {
>> +               uint32_t PhysicalAddress;
>> +               uint32_t VirtualSize;
>> +       } Misc;
>> +       uint32_t VirtualAddress;
>> +       uint32_t SizeOfRawData;
>> +       uint32_t PointerToRawData;
>> +       uint32_t PointerToRelocations;
>> +       uint32_t PointerToLinenumbers;
>> +       uint16_t        NumberOfRelocations;
>> +       uint16_t        NumberOfLinenumbers;
>> +       uint32_t Characteristics;
>> +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
>> +
>> +#define IMAGE_DIRECTORY_ENTRY_BASERELOC         5
>> +
>> +typedef struct _IMAGE_BASE_RELOCATION
>> +{
>> +        uint32_t VirtualAddress;
>> +        uint32_t SizeOfBlock;
>> +        /* WORD TypeOffset[1]; */
>> +} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION;
>> +
>> +typedef struct _IMAGE_RELOCATION
>> +{
>> +       union {
>> +               uint32_t   VirtualAddress;
>> +               uint32_t   RelocCount;
>> +       } DUMMYUNIONNAME;
>> +       uint32_t   SymbolTableIndex;
>> +       uint16_t        Type;
>> +} IMAGE_RELOCATION, *PIMAGE_RELOCATION;
>> +
>> +#define IMAGE_SIZEOF_RELOCATION 10
>> +
>> +/* generic relocation types */
>> +#define IMAGE_REL_BASED_ABSOLUTE                0
>> +#define IMAGE_REL_BASED_HIGH                    1
>> +#define IMAGE_REL_BASED_LOW                     2
>> +#define IMAGE_REL_BASED_HIGHLOW                 3
>> +#define IMAGE_REL_BASED_HIGHADJ                 4
>> +#define IMAGE_REL_BASED_MIPS_JMPADDR            5
>> +#define IMAGE_REL_BASED_ARM_MOV32A              5 /* yes, 5 too */
>> +#define IMAGE_REL_BASED_ARM_MOV32               5 /* yes, 5 too */
>> +#define IMAGE_REL_BASED_SECTION                 6
>> +#define IMAGE_REL_BASED_REL                     7
>> +#define IMAGE_REL_BASED_ARM_MOV32T              7 /* yes, 7 too */
>> +#define IMAGE_REL_BASED_THUMB_MOV32             7 /* yes, 7 too */
>> +#define IMAGE_REL_BASED_MIPS_JMPADDR16          9
>> +#define IMAGE_REL_BASED_IA64_IMM64              9 /* yes, 9 too */
>> +#define IMAGE_REL_BASED_DIR64                   10
>> +#define IMAGE_REL_BASED_HIGH3ADJ                11
>> +
>> +/* ARM relocation types */
>> +#define IMAGE_REL_ARM_ABSOLUTE          0x0000
>> +#define IMAGE_REL_ARM_ADDR              0x0001
>> +#define IMAGE_REL_ARM_ADDR32NB          0x0002
>> +#define IMAGE_REL_ARM_BRANCH24          0x0003
>> +#define IMAGE_REL_ARM_BRANCH11          0x0004
>> +#define IMAGE_REL_ARM_TOKEN             0x0005
>> +#define IMAGE_REL_ARM_GPREL12           0x0006
>> +#define IMAGE_REL_ARM_GPREL7            0x0007
>> +#define IMAGE_REL_ARM_BLX24             0x0008
>> +#define IMAGE_REL_ARM_BLX11             0x0009
>> +#define IMAGE_REL_ARM_SECTION           0x000E
>> +#define IMAGE_REL_ARM_SECREL            0x000F
>> +#define IMAGE_REL_ARM_MOV32A            0x0010
>> +#define IMAGE_REL_ARM_MOV32T            0x0011
>> +#define IMAGE_REL_ARM_BRANCH20T 0x0012
>> +#define IMAGE_REL_ARM_BRANCH24T 0x0014
>> +#define IMAGE_REL_ARM_BLX23T            0x0015
>> +
>> +/* ARM64 relocation types */
>> +#define IMAGE_REL_ARM64_ABSOLUTE        0x0000
>> +#define IMAGE_REL_ARM64_ADDR32          0x0001
>> +#define IMAGE_REL_ARM64_ADDR32NB        0x0002
>> +#define IMAGE_REL_ARM64_BRANCH26        0x0003
>> +#define IMAGE_REL_ARM64_PAGEBASE_REL21  0x0004
>> +#define IMAGE_REL_ARM64_REL21           0x0005
>> +#define IMAGE_REL_ARM64_PAGEOFFSET_12A  0x0006
>> +#define IMAGE_REL_ARM64_PAGEOFFSET_12L  0x0007
>> +#define IMAGE_REL_ARM64_SECREL          0x0008
>> +#define IMAGE_REL_ARM64_SECREL_LOW12A   0x0009
>> +#define IMAGE_REL_ARM64_SECREL_HIGH12A  0x000A
>> +#define IMAGE_REL_ARM64_SECREL_LOW12L   0x000B
>> +#define IMAGE_REL_ARM64_TOKEN           0x000C
>> +#define IMAGE_REL_ARM64_SECTION         0x000D
>> +#define IMAGE_REL_ARM64_ADDR64          0x000E
>> +
>> +/* AMD64 relocation types */
>> +#define IMAGE_REL_AMD64_ABSOLUTE        0x0000
>> +#define IMAGE_REL_AMD64_ADDR64          0x0001
>> +#define IMAGE_REL_AMD64_ADDR32          0x0002
>> +#define IMAGE_REL_AMD64_ADDR32NB        0x0003
>> +#define IMAGE_REL_AMD64_REL32           0x0004
>> +#define IMAGE_REL_AMD64_REL32_1         0x0005
>> +#define IMAGE_REL_AMD64_REL32_2         0x0006
>> +#define IMAGE_REL_AMD64_REL32_3         0x0007
>> +#define IMAGE_REL_AMD64_REL32_4         0x0008
>> +#define IMAGE_REL_AMD64_REL32_5         0x0009
>> +#define IMAGE_REL_AMD64_SECTION         0x000A
>> +#define IMAGE_REL_AMD64_SECREL          0x000B
>> +#define IMAGE_REL_AMD64_SECREL7         0x000C
>> +#define IMAGE_REL_AMD64_TOKEN           0x000D
>> +#define IMAGE_REL_AMD64_SREL32          0x000E
>> +#define IMAGE_REL_AMD64_PAIR            0x000F
>> +#define IMAGE_REL_AMD64_SSPAN32         0x0010
>> +
>> +#endif /* _PE_H */
>> diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
>> new file mode 100644
>> index 0000000..a7788bf
>> --- /dev/null
>> +++ b/lib/efi_loader/efi_image_loader.c
>> @@ -0,0 +1,178 @@
>> +/*
>> + *  EFI image loader
>> + *
>> + *  based partly on wine code
>> + *
>> + *  Copyright (c) 2016 Alexander Graf
>> + *
>> + *  SPDX-License-Identifier:     GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <pe.h>
>> +#include <efi_loader.h>
> This should go above pe.h to keep alpha ordering.
>
>> +#include <asm/global_data.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +#define ROUND_UP(val, round) ((val + (round - 1)) & ~(round - 1))
> Can you use round_up()?

Turns out this just disappears with the new memory code :).

>
>> +#define MB (1024 * 1024)
>> +
>> +const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID;
>> +const efi_guid_t efi_guid_loaded_image = LOADED_IMAGE_GUID;
>> +
>> +efi_status_t efi_return_handle(void *handle, efi_guid_t *protocol,
>> +                       void **protocol_interface, void *agent_handle,
>> +                       void *controller_handle, uint32_t attributes)
>> +{
>> +       *protocol_interface = handle;
>> +       return EFI_SUCCESS;
>> +}
>> +
>> +/* Will be implemented in a later patch */
>> +void *efi_loader_alloc(uint64_t len)
>> +{
>> +       return NULL;
>> +}
>> +
>> +/*
>> + * This function loads all sections from a PE binary into a newly reserved
>> + * piece of memory. On successful load it then returns the entry point for
>> + * the binary. Otherwise NULL.
>> + */
>> +void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
>> +{
>> +       IMAGE_NT_HEADERS32 *nt;
>> +       IMAGE_DOS_HEADER *dos;
>> +       IMAGE_SECTION_HEADER *sections;
>> +       int num_sections;
>> +       void *efi_reloc;
>> +       int i;
>> +       const uint16_t *relocs;
>> +       const IMAGE_BASE_RELOCATION *rel;
>> +       const IMAGE_BASE_RELOCATION *end;
>> +       unsigned long rel_size;
>> +       int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC;
>> +       void *entry;
>> +       uint64_t image_size;
>> +       unsigned long virt_size = 0;
>> +       bool can_run_nt64 = true;
>> +       bool can_run_nt32 = true;
> What does nt stand for?

This is PE speech :). These headers probably got introduced back with 
Windows NT, so that's why they're called that way.

>
>> +
>> +#if defined(CONFIG_ARM64)
>> +       can_run_nt32 = false;
>> +#elif defined(CONFIG_ARM)
>> +       can_run_nt64 = false;
>> +#endif
>> +
>> +       dos = efi;
>> +       if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
>> +               printf("%s: Invalid DOS Signature\n", __func__);
>> +               return NULL;
>> +       }
>> +
>> +       nt = (void *) ((char *)efi + dos->e_lfanew);
>> +       if (nt->Signature != IMAGE_NT_SIGNATURE) {
>> +               printf("%s: Invalid NT Signature\n", __func__);
>> +               return NULL;
>> +       }
>> +
>> +       /* Calculate upper virtual address boundary */
>> +       num_sections = nt->FileHeader.NumberOfSections;
>> +       sections = (void *)&nt->OptionalHeader +
>> +                           nt->FileHeader.SizeOfOptionalHeader;
>> +
>> +       for (i = num_sections - 1; i >= 0; i--) {
>> +               IMAGE_SECTION_HEADER *sec = &sections[i];
>> +               virt_size = max_t(unsigned long, virt_size,
>> +                                 sec->VirtualAddress + sec->Misc.VirtualSize);
>> +       }
>> +
>> +       /* Read 32/64bit specific header bits */
>> +       if (can_run_nt64 &&
>> +           (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)) {
>> +               IMAGE_NT_HEADERS64 *nt64 = (void *)nt;
>> +               IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader;
>> +               image_size = opt->SizeOfImage;
>> +               efi_reloc = efi_loader_alloc(virt_size);
>> +               if (!efi_reloc) {
>> +                       printf("%s: Could not allocate %ld bytes\n",
>> +                               __func__, virt_size);
>> +                       return NULL;
>> +               }
>> +               entry = efi_reloc + opt->AddressOfEntryPoint;
>> +               rel_size = opt->DataDirectory[rel_idx].Size;
>> +               rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
>> +       } else if (can_run_nt32 &&
>> +                  (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)) {
>> +               IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
>> +               image_size = opt->SizeOfImage;
>> +               efi_reloc = efi_loader_alloc(virt_size);
>> +               if (!efi_reloc) {
>> +                       printf("%s: Could not allocate %ld bytes\n",
>> +                               __func__, virt_size);
>> +                       return NULL;
>> +               }
>> +               entry = efi_reloc + opt->AddressOfEntryPoint;
>> +               rel_size = opt->DataDirectory[rel_idx].Size;
>> +               rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
>> +       } else {
>> +               printf("%s: Invalid optional header magic %x\n", __func__,
>> +                      nt->OptionalHeader.Magic);
>> +               return NULL;
>> +       }
>> +
>> +       /* Load sections into RAM */
>> +       for (i = num_sections - 1; i >= 0; i--) {
>> +               IMAGE_SECTION_HEADER *sec = &sections[i];
>> +               memset(efi_reloc + sec->VirtualAddress, 0,
>> +                      sec->Misc.VirtualSize);
>> +               memcpy(efi_reloc + sec->VirtualAddress,
>> +                      efi + sec->PointerToRawData,
>> +                      sec->SizeOfRawData);
>> +       }
>> +
>> +       /* Run through relocations */
>> +       end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size);
>> +
>> +       while (rel < end - 1 && rel->SizeOfBlock) {
>> +               relocs = (const uint16_t *)(rel + 1);
>> +               i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t);
>> +               while (i--) {
>> +                       uint16_t offset = (*relocs & 0xfff) + rel->VirtualAddress;
>> +                       int type = *relocs >> 12;
>> +                       unsigned long delta = (unsigned long)efi_reloc;
>> +                       uint64_t *x64 = efi_reloc + offset;
>> +                       uint32_t *x32 = efi_reloc + offset;
>> +                       uint16_t *x16 = efi_reloc + offset;
>> +
>> +                       switch (type) {
>> +                       case IMAGE_REL_BASED_ABSOLUTE:
>> +                               break;
>> +                       case IMAGE_REL_BASED_HIGH:
>> +                               *x16 += ((uint32_t)delta) >> 16;
>> +                               break;
>> +                       case IMAGE_REL_BASED_LOW:
>> +                               *x16 += (uint16_t)delta;
>> +                               break;
>> +                       case IMAGE_REL_BASED_HIGHLOW:
>> +                               *x32 += (uint32_t)delta;
>> +                               break;
>> +                       case IMAGE_REL_BASED_DIR64:
>> +                               *x64 += (uint64_t)delta;
>> +                               break;
>> +                       default:
>> +                               printf("Unknown Relocation off %x type %x\n",
>> +                                      offset, type);
>> +                       }
>> +                       relocs++;
>> +               }
>> +               rel = (const IMAGE_BASE_RELOCATION *)relocs;
>> +       }
> How about putting the relocation code in a separate function, as this
> one is getting large.

Great idea.


Alex



More information about the U-Boot mailing list