3
|
1 #include <efi.h>
|
|
2 #include <efilib.h>
|
|
3
|
|
4 #include <efi.h>
|
|
5 #include <efilib.h>
|
|
6
|
8
|
7 struct rsdp {
|
|
8 CHAR8 sig[8];
|
|
9 UINT8 Checksum;
|
|
10 CHAR8 OEMID[6];
|
|
11 UINT8 Revision;
|
|
12 UINT32 RsdtAddress;
|
|
13 UINT32 Len;
|
|
14 UINT64 XsdtAddress;
|
|
15 UINT8 ExtChecksum;
|
|
16 UINT8 reserved[3];
|
|
17 };
|
|
18
|
|
19 struct __attribute((packed)) GraphicConfig {
|
|
20 UINT64 frame_base;
|
|
21 UINT64 frame_size;
|
|
22 UINT64 horizontal_resolution;
|
|
23 UINT64 vertical_resolution;
|
|
24 UINT64 pixels_per_scan_line;
|
|
25 };
|
|
26
|
3
|
27 struct __attribute__((packed)) BootParam {
|
|
28 UINT64 kernel_entry;
|
|
29 UINT64 rsdp_addr;
|
8
|
30 struct GraphicConfig graphic_config;
|
3
|
31 // struct gdt bootstrap_gdt[3];
|
|
32 // struct gdt_desc bootstrap_gdt_desc;
|
|
33 UINT64 kernel_addr;
|
|
34 };
|
|
35
|
8
|
36
|
|
37
|
3
|
38 struct MemoryMap {
|
|
39 UINTN BufferSize;
|
|
40 VOID *Buffer;
|
|
41 UINTN MapSize;
|
|
42 UINTN MapKey;
|
|
43 UINTN DescriptorSize;
|
|
44 UINT32 DescriptorVersion;
|
|
45 };
|
0
|
46
|
7
|
47 void HexDump(UINT8 *bytePtr, UINTN size) {
|
|
48 for (UINTN i = 0; i < size; i++) {
|
|
49 if (i % 16 == 0 && i != 0) {
|
|
50 Print(L"\n");
|
|
51 }
|
|
52 Print(L"%02x ", bytePtr[i]);
|
|
53 }
|
|
54 Print(L"\n");
|
|
55 }
|
|
56
|
0
|
57
|
5
|
58 EFI_STATUS LoadFile(CHAR16 *FileName, EFI_PHYSICAL_ADDRESS *FileAddr, UINTN *FilePageSize) {
|
3
|
59 EFI_STATUS Status;
|
|
60 EFI_FILE_IO_INTERFACE *IOVolume;
|
|
61 EFI_FILE_HANDLE Root;
|
|
62 EFI_FILE_HANDLE File;
|
|
63 Print(L"LoadFile\n");
|
|
64
|
5
|
65 // Locate all handles that support the Simple File System Protocol.
|
|
66 UINTN HandleCount = 5;
|
|
67 void **HandleBuffer;
|
|
68 Status = LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &HandleCount, &HandleBuffer);
|
3
|
69 if (EFI_ERROR(Status)) {
|
5
|
70 Print(L"Failed to locate handles for file system protocol: %r\n", Status);
|
3
|
71 return Status;
|
|
72 }
|
0
|
73
|
5
|
74 for (UINTN Index = 0; Index < HandleCount; Index++) {
|
|
75 // Try to open the file system
|
|
76 Status = uefi_call_wrapper(BS->HandleProtocol, 3, HandleBuffer[Index], &FileSystemProtocol, (void **)&IOVolume);
|
|
77
|
|
78 if (!EFI_ERROR(Status)) {
|
|
79 // Open the root directory
|
|
80 Status = uefi_call_wrapper(IOVolume->OpenVolume, 2, IOVolume, &Root);
|
|
81 if (EFI_ERROR(Status)) {
|
|
82 Print(L"Failed to open root directory: %r\n", Status);
|
|
83 continue;
|
|
84 }
|
|
85
|
|
86 // Now open a file
|
|
87 Status = uefi_call_wrapper(Root->Open, 5, Root, &File,FileName , EFI_FILE_MODE_READ, 0);
|
|
88 if (EFI_ERROR(Status)) {
|
6
|
89 // Print(L"Failed to open file: %r\n", Status);
|
5
|
90 uefi_call_wrapper(Root->Close, 1, Root);
|
|
91 continue;
|
|
92 }
|
|
93
|
|
94 EFI_FILE_INFO *FileInfo;
|
|
95 UINTN FileInfoSize;
|
|
96 FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
|
|
97 FileInfo = AllocatePool(FileInfoSize);
|
|
98 Status = uefi_call_wrapper(File->GetInfo, 4, File, &gEfiFileInfoGuid, &FileInfoSize, FileInfo);
|
|
99 if (EFI_ERROR(Status)) {
|
|
100 Print(L"Failed to get file info.\n");
|
|
101 FreePool(FileInfo);
|
|
102 return Status;
|
|
103 }
|
|
104
|
|
105 UINTN FileSize = FileInfo->FileSize;
|
|
106 Print(L"FileSize = %d\n", FileSize);
|
|
107 *FilePageSize = (FileSize + 4095) / 4096;
|
8
|
108 *FileAddr = 0x40000000;
|
9
|
109 Status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateAddress, EfiBootServicesCode, *FilePageSize, FileAddr);
|
5
|
110 if (EFI_ERROR(Status)) {
|
|
111 Print(L"Failed to allocate pages.\n");
|
|
112 FreePool(FileInfo);
|
|
113 return Status;
|
|
114 }
|
|
115
|
8
|
116 // skip header
|
|
117 FileSize = 0x1000;
|
|
118 Status = uefi_call_wrapper(File->Read, 3, File, &FileSize, (VOID *)*FileAddr);
|
|
119 if (EFI_ERROR(Status)) {
|
|
120 Print(L"Failed to load file.\n");
|
|
121 FreePool(FileInfo);
|
|
122 return Status;
|
|
123 }
|
|
124
|
|
125 // load binary part
|
|
126 FileSize = FileInfo->FileSize-0x1000;
|
5
|
127 Status = uefi_call_wrapper(File->Read, 3, File, &FileSize, (VOID *)*FileAddr);
|
|
128 if (EFI_ERROR(Status)) {
|
|
129 Print(L"Failed to load file.\n");
|
|
130 FreePool(FileInfo);
|
|
131 return Status;
|
|
132 }
|
|
133 Print(L"Successfully loaded file: %s\n", FileName);
|
|
134
|
|
135 FreePool(FileInfo);
|
|
136 // Close the file and root directory
|
|
137 uefi_call_wrapper(File->Close, 1, File);
|
|
138 uefi_call_wrapper(Root->Close, 1, Root);
|
|
139 }
|
3
|
140 }
|
|
141
|
|
142
|
|
143 return Status;
|
|
144 }
|
|
145
|
9
|
146 UINT64 ReadCurrentEL() {
|
|
147 UINT64 currentEL;
|
|
148 __asm__ volatile("MRS %0, CurrentEL" : "=r" (currentEL));
|
|
149 return (currentEL >> 2) & 0x3; // Extract EL value
|
|
150 }
|
|
151
|
|
152 void DumpLoadedImageProtocol(EFI_LOADED_IMAGE *LoadedImage) {
|
|
153 Print(L"Dumping EFI_LOADED_IMAGE_PROTOCOL\n");
|
|
154 Print(L"Revision: %x\n", LoadedImage->Revision);
|
|
155 Print(L"ParentHandle: %x\n", LoadedImage->ParentHandle);
|
|
156 Print(L"SystemTable: %x\n", LoadedImage->SystemTable);
|
|
157
|
|
158 Print(L"DeviceHandle: %x\n", LoadedImage->DeviceHandle);
|
|
159 Print(L"FilePath: %s\n", DevicePathToStr(LoadedImage->FilePath));
|
|
160 // Note: LoadedImage->Reserved is not dumped as it's meant to be NULL/unused
|
|
161
|
|
162 Print(L"LoadOptionsSize: %x\n", LoadedImage->LoadOptionsSize);
|
|
163 Print(L"LoadOptions: %s\n", LoadedImage->LoadOptions);
|
|
164
|
|
165 Print(L"ImageBase: %x\n", LoadedImage->ImageBase);
|
|
166 Print(L"ImageSize: %lx\n", LoadedImage->ImageSize);
|
|
167 Print(L"ImageCodeType: %x\n", LoadedImage->ImageCodeType);
|
|
168 Print(L"ImageDataType: %x\n", LoadedImage->ImageDataType);
|
|
169
|
|
170 if (LoadedImage->Unload != NULL) {
|
|
171 Print(L"Unload: %x\n", LoadedImage->Unload);
|
|
172 } else {
|
|
173 Print(L"Unload: NULL\n");
|
|
174 }
|
|
175 }
|
|
176
|
3
|
177 EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
|
178
|
|
179 EFI_STATUS Status;
|
|
180 CHAR16 *KernelFileName = L"\\kernel";
|
|
181 EFI_PHYSICAL_ADDRESS KernelBaseAddr;
|
|
182
|
|
183 InitializeLib(ImageHandle, SystemTable);
|
|
184 Print(L"Initializeing\n");
|
|
185 UINTN BufferPageSize;
|
5
|
186
|
3
|
187 Print(L"LoadFile: %s\n", KernelFileName);
|
5
|
188
|
|
189 Status = LoadFile(KernelFileName, &KernelBaseAddr, &BufferPageSize);
|
0
|
190 if (EFI_ERROR(Status)) {
|
|
191 return Status;
|
|
192 }
|
6
|
193 Print(L"Boot 1\n");
|
3
|
194
|
|
195 struct BootParam boot_param;
|
7
|
196 boot_param.kernel_addr = KernelBaseAddr ;
|
|
197 boot_param.kernel_entry = boot_param.kernel_addr ;
|
3
|
198 // GetGraphicMode(ImageHandle, &(boot_param.graphic_config));
|
|
199
|
|
200
|
6
|
201 Print(L"Boot 2\n");
|
3
|
202
|
8
|
203 void **rsdp = NULL;
|
|
204 EFI_GUID AcpiTableGuid = ACPI_20_TABLE_GUID; // Use ACPI 2.0 table GUID
|
|
205
|
|
206 Status = LibGetSystemConfigurationTable(&AcpiTableGuid, (void **)&rsdp);
|
|
207 if (EFI_ERROR(Status) || rsdp == NULL) {
|
|
208 Print(L"Error getting ACPI table: %r\n", Status);
|
|
209 return Status;
|
|
210 } else {
|
|
211 boot_param.rsdp_addr = (UINT64)rsdp;
|
|
212 }
|
|
213
|
|
214 Print(L"Boot 3\n");
|
|
215
|
3
|
216 struct MemoryMap MemoryMap = {4096, NULL, 4096, 0, 0, 0};
|
|
217 Status = uefi_call_wrapper(SystemTable->BootServices->AllocatePool, 3, EfiLoaderData, MemoryMap.BufferSize, &MemoryMap.Buffer);
|
0
|
218 if (EFI_ERROR(Status)) {
|
3
|
219 Print(L"Failed to allocate memory to get memory map\n");
|
0
|
220 return Status;
|
|
221 }
|
3
|
222
|
|
223 Status = uefi_call_wrapper(SystemTable->BootServices->GetMemoryMap, 5, &MemoryMap.MapSize, (EFI_MEMORY_DESCRIPTOR*)MemoryMap.Buffer, &MemoryMap.MapKey, &MemoryMap.DescriptorSize, &MemoryMap.DescriptorVersion);
|
|
224 if (EFI_ERROR(Status)) {
|
|
225 Print(L"Failed to get memory map.\n");
|
|
226 return Status;
|
|
227 }
|
8
|
228 Print(L"Boot r4\n");
|
0
|
229
|
7
|
230 Print(L"Kernel Entry: %llx\n",boot_param.kernel_entry);
|
|
231 Print(L"RSDP Address: %llx\n",boot_param.rsdp_addr);
|
|
232 Print(L"Kernel Address: %llx\n",boot_param.kernel_addr);
|
|
233
|
|
234 HexDump((UINT8 *)KernelBaseAddr,0x100);
|
|
235
|
9
|
236 EFI_DEVICE_PATH *Path;
|
|
237 EFI_LOADED_IMAGE *LoadedImageParent;
|
|
238 EFI_LOADED_IMAGE *LoadedImage;
|
|
239 EFI_HANDLE Image;
|
|
240 CHAR16 *Options = L"root=/dev/sda2 rootfstype=btrfs rw quiet splash";
|
|
241
|
|
242 Status = uefi_call_wrapper(BS->OpenProtocol, 6, ImageHandle, &LoadedImageProtocol,(void**)&LoadedImageParent, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
243 if (EFI_ERROR(Status)) {
|
|
244 Print(L"Could not get LoadedImageProtocol handler %r\n", Status);
|
|
245 return Status;
|
|
246 }
|
|
247 Print(L"Hello,2!\n");
|
|
248 if (0) {
|
|
249 Path = FileDevicePath(LoadedImageParent->DeviceHandle, L"\\kernel");
|
|
250 if (Path == NULL) {
|
|
251 Print(L"Could not get device path.");
|
|
252 return EFI_INVALID_PARAMETER;
|
|
253 }
|
|
254 Print(L"Hello,3!\n");
|
|
255 Status = uefi_call_wrapper(BS->LoadImage, 6, FALSE, ImageHandle, Path, NULL, 0, &Image);
|
|
256 if (EFI_ERROR(Status)) {
|
|
257 Print(L"Could not load %r", Status);
|
|
258 FreePool(Path);
|
|
259 return Status;
|
|
260 }
|
|
261 Print(L"Hello,4!\n");
|
|
262 Status = uefi_call_wrapper(BS->OpenProtocol, 6, Image, &LoadedImageProtocol, (void**)&LoadedImage, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
263 if (EFI_ERROR(Status)) {
|
|
264 Print(L"Could not get LoadedImageProtocol handler %r\n", Status);
|
|
265 uefi_call_wrapper(BS->UnloadImage, 1, Image);
|
|
266 FreePool(Path);
|
|
267 return Status;
|
|
268 }
|
|
269 Print(L"Hello,5!\n");
|
|
270 LoadedImage->LoadOptions = Options;
|
|
271 LoadedImage->LoadOptionsSize = (StrLen(LoadedImage->LoadOptions)+1) * sizeof(CHAR16);
|
|
272
|
|
273 DumpLoadedImageProtocol (LoadedImage);
|
|
274
|
3
|
275 Status = uefi_call_wrapper(SystemTable->BootServices->ExitBootServices, 2, ImageHandle, MemoryMap.MapKey);
|
|
276 if (EFI_ERROR(Status)) {
|
|
277 Print(L"Failed to exit boot services\n");
|
|
278 return Status;
|
|
279 }
|
|
280
|
9
|
281 // Start the image
|
|
282 Status = uefi_call_wrapper(SystemTable->BootServices->StartImage, 3, Image, NULL, NULL);
|
|
283
|
|
284 uefi_call_wrapper(BS->UnloadImage, 1, Image);
|
|
285 FreePool(Path);
|
|
286
|
|
287 } else {
|
|
288
|
|
289 UINT64 el = ReadCurrentEL();
|
|
290 Print(L"Current Exception Level: %d\n", el);
|
|
291
|
|
292 Status = uefi_call_wrapper(SystemTable->BootServices->ExitBootServices, 2, ImageHandle, MemoryMap.MapKey);
|
|
293 if (EFI_ERROR(Status)) {
|
|
294 Print(L"Failed to exit boot services\n");
|
|
295 return Status;
|
|
296
|
|
297 }
|
|
298
|
|
299
|
|
300 // Inline assembly to jump to the kernel
|
|
301 // __asm__ volatile("br %0" : : "r"(0x40000000));
|
|
302
|
|
303 typedef unsigned long (EntryPoint)(struct BootParam*);
|
|
304 EntryPoint *Entry = (EntryPoint*)(KernelBaseAddr);
|
3
|
305 Entry(&boot_param);
|
|
306
|
9
|
307 }
|
|
308
|
3
|
309 return Status;
|
0
|
310 }
|
3
|
311
|
|
312
|
|
313
|
|
314
|