1/* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17// Refer to https://llvm.org/doxygen/Object_2COFF_8h_source.html and Microsoft Portable Executable 18// and Common Object File Format Specification for more detail. 19 20// See https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#machine-types 21#define IMAGE_FILE_MACHINE_RISCV64 0x5064 22 23// See https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#characteristics 24#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 25 26// See https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-image-only 27#define PE32_PLUS_HEADER_MAGIC 0x020b 28 29// See https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#windows-subsystem 30#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 31 32.macro DATA_DIRECTORY name 33\name\()_data_directory: 34 .long 0 // support::ulittle32_t RelativeVirtualAddress; 35 .long 0 // support::ulittle32_t Size; 36.endm 37 38.section .efi_header,"a" 39.global dos_header 40 41// MS-DOS Stub 42dos_header: 43 .short 0x5a4d // Magic 'MZ' 44 .short 0 // support::ulittle16_t UsedBytesInTheLastPage; 45 .short 0 // support::ulittle16_t FileSizeInPages; 46 .short 0 // support::ulittle16_t NumberOfRelocationItems; 47 .short 0 // support::ulittle16_t HeaderSizeInParagraphs; 48 .short 0 // support::ulittle16_t MinimumExtraParagraphs; 49 .short 0 // support::ulittle16_t MaximumExtraParagraphs; 50 .short 0 // support::ulittle16_t InitialRelativeSS; 51 .short 0 // support::ulittle16_t InitialSP; 52 .short 0 // support::ulittle16_t Checksum; 53 .short 0 // support::ulittle16_t InitialIP; 54 .short 0 // support::ulittle16_t InitialRelativeCS; 55 .short 0 // support::ulittle16_t AddressOfRelocationTable; 56 .short 0 // support::ulittle16_t OverlayNumber; 57 .skip 2*4 // support::ulittle16_t Reserved[4]; 58 .short 0 // support::ulittle16_t OEMid; 59 .short 0 // support::ulittle16_t OEMinfo; 60 .skip 2*10 // support::ulittle16_t Reserved2[10]; 61 // Even though we fixed `dos_header` at 0x00, we still need to subtract it to 62 // indicate this is relative offset. Otherwise linker complains about referencing 63 // an absolute address when linking with `-fPIE` (position independent executable) 64 .long signature - dos_header // support::ulittle32_t AddressOfNewExeHeader; 65 66// Signature 67signature: 68 .long 0x00004550 // "PE\0\0" 69 70// COFF File Header 71coff_file_header: 72 .short IMAGE_FILE_MACHINE_RISCV64 // support::ulittle16_t Machine; 73 // ".reloc" and ".text" 74 .short 2 // support::ulittle16_t NumberOfSections; 75 .long 0 // support::ulittle32_t TimeDateStamp; 76 .long 0 // support::ulittle32_t PointerToSymbolTable; 77 .long 0 // support::ulittle32_t NumberOfSymbols; 78 .short section_table_start - pe32plus_header // support::ulittle16_t SizeOfOptionalHeader; 79 .short IMAGE_FILE_EXECUTABLE_IMAGE // support::ulittle16_t Characteristics; 80 81// PE32+ Optional Header 82pe32plus_header: 83 .short PE32_PLUS_HEADER_MAGIC // support::ulittle16_t Magic; 84 .byte 0 // uint8_t MajorLinkerVersion; 85 .byte 0 // uint8_t MinorLinkerVersion; 86 .long _end - dos_header // support::ulittle32_t SizeOfCode; 87 .long 0 // support::ulittle32_t SizeOfInitializedData; 88 .long 0 // support::ulittle32_t SizeOfUninitializedData; 89 .long _start - dos_header // support::ulittle32_t AddressOfEntryPoint; 90 .long dos_header - dos_header // support::ulittle32_t BaseOfCode; 91 .quad 0 // support::ulittle64_t ImageBase; 92 .long 512 // support::ulittle32_t SectionAlignment; 93 .long 512 // support::ulittle32_t FileAlignment; 94 .short 0 // support::ulittle16_t MajorOperatingSystemVersion; 95 .short 0 // support::ulittle16_t MinorOperatingSystemVersion; 96 .short 0 // support::ulittle16_t MajorImageVersion; 97 .short 0 // support::ulittle16_t MinorImageVersion; 98 .short 0 // support::ulittle16_t MajorSubsystemVersion; 99 .short 0 // support::ulittle16_t MinorSubsystemVersion; 100 .long 0 // support::ulittle32_t Win32VersionValue; 101 .long _end - dos_header // support::ulittle32_t SizeOfImage; 102 .long end_of_header - dos_header // support::ulittle32_t SizeOfHeaders; 103 .long 0 // support::ulittle32_t CheckSum; 104 .short IMAGE_SUBSYSTEM_EFI_APPLICATION // support::ulittle16_t Subsystem; 105 .short 0 // support::ulittle16_t DLLCharacteristics; 106 .quad 0 // support::ulittle64_t SizeOfStackReserve; 107 .quad 0 // support::ulittle64_t SizeOfStackCommit; 108 .quad 0 // support::ulittle64_t SizeOfHeapReserve; 109 .quad 0 // support::ulittle64_t SizeOfHeapCommit; 110 .long 0 // support::ulittle32_t LoaderFlags; 111 // 16 data directories in total 112 .long 16 // support::ulittle32_t NumberOfRvaAndSize; 113 114 // The following are data directories mostly for place holder purpose for now. Entries 115 // such as certification_table might be needed for secure boot in the future. 116 DATA_DIRECTORY export_table 117 DATA_DIRECTORY import_table 118 DATA_DIRECTORY resource_table 119 DATA_DIRECTORY exception_table 120 DATA_DIRECTORY certification_table 121 DATA_DIRECTORY base_relocation_table 122 DATA_DIRECTORY debug 123 DATA_DIRECTORY architecture_data 124 DATA_DIRECTORY global_ptr 125 DATA_DIRECTORY tls_table 126 DATA_DIRECTORY load_config_table 127 DATA_DIRECTORY bound_inport 128 DATA_DIRECTORY import_address_table 129 DATA_DIRECTORY delay_import_descriptor 130 DATA_DIRECTORY CLR_runtime_header 131 .quad 0 132 133// Section Table 134section_table_start: 135// .reloc. May be expected by some PE32+ loader 136reloc_section: 137 .ascii ".reloc" 138 .byte 0 139 .byte 0 // 8 bytes of `char Name[COFF::NameSize];` 140 .long 0 // support::ulittle32_t VirtualSize; 141 .long 0 // support::ulittle32_t VirtualAddress; 142 .long 0 // support::ulittle32_t SizeOfRawData; 143 .long 0 // support::ulittle32_t PointerToRawData; 144 .long 0 // support::ulittle32_t PointerToRelocations; 145 .long 0 // support::ulittle32_t PointerToLinenumbers; 146 .short 0 // support::ulittle16_t NumberOfRelocations; 147 .short 0 // support::ulittle16_t NumberOfLinenumbers; 148 // https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#section-flags 149 // We use the same value as Clang would generate with "-Wl,/subsystem:efi_application" 150 // IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE | 151 // IMAGE_SCN_MEM_READ 152 .long 0x42000040 // support::ulittle32_t Characteristics; 153 154// .text 155text_section: 156 .ascii ".text" 157 .byte 0 158 .byte 0 159 .byte 0 // 8 bytes of `char Name[COFF::NameSize];` 160 .long _end - end_of_header // support::ulittle32_t VirtualSize; 161 .long end_of_header - dos_header // support::ulittle32_t VirtualAddress; 162 .long _end - end_of_header // support::ulittle32_t SizeOfRawData; 163 .long end_of_header - dos_header // support::ulittle32_t PointerToRawData; 164 .long 0 // support::ulittle32_t PointerToRelocations; 165 .long 0 // support::ulittle32_t PointerToLinenumbers; 166 .short 0 // support::ulittle16_t NumberOfRelocations; 167 .short 0 // support::ulittle16_t NumberOfLinenumbers; 168 // IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA | 169 // IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ 170 // We use the same value as Clang would generate with "-Wl,/subsystem:efi_application" 171 .long 0x60000020 // support::ulittle32_t Characteristics; 172 173end_of_header: 174 175// Traditionally, PE/COFF header occupies the entire first page. We keep this pattern. 176.align 9 177 178_start: 179 // Behave like a function call. 180 addi sp, sp, -8*3 181 sd ra, 0(sp) 182 sd t0, 8(sp) 183 sd t1, 16(sp) 184 185 // Save the EFI image handle from a0 186 mv t0, a0 187 // Save the EFI system table from a1 188 mv t1, a1 189 190 // Get the program load address (same as dos_header), and .dynamic section address. 191 lla a0, dos_header 192 lla a1, _DYNAMIC 193 // Apply relocation fixup 194 call ApplyRelocationHangIfFail 195 196 // Now call efi_main. 197 mv a0, t0 198 mv a1, t1 199 call efi_main 200 201 // Prepare to return. 202 ld ra, 0(sp) 203 ld t0, 8(sp) 204 ld t1, 16(sp) 205 add sp, sp, 8*3 206 ret 207