PatchworkOS
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1#include "disk.h"
2#include "gop.h"
3#include "kernel.h"
4#include "mem.h"
5
6#include <boot/boot_info.h>
7#include <kernel/mem/paging.h>
8#include <kernel/version.h>
9
10#include <efi.h>
11#include <efilib.h>
12
13#define EXIT_BOOT_SERVICES_MAX_RETRY 5
14
15static void splash_screen(void)
16{
17#ifdef NDEBUG
18 Print(L"Start %a-bootloader %a (Built %a %a)\n", OS_NAME, OS_VERSION, __DATE__, __TIME__);
19#else
20 Print(L"Start %a-bootloader DEBUG %a (Built %a %a)\n", OS_NAME, OS_VERSION, __DATE__, __TIME__);
21#endif
22 Print(L"Copyright (C) 2025 Kai Norberg. MIT Licensed. See /usr/license/LICENSE for details.\n");
23}
24
25static EFI_STATUS open_root_volume(EFI_FILE** file, EFI_HANDLE imageHandle)
26{
27 EFI_LOADED_IMAGE* loaded_image = 0;
28 EFI_GUID lipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
29 EFI_FILE_IO_INTERFACE* IOVolume;
30 EFI_GUID fsGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
31
32 EFI_STATUS status = uefi_call_wrapper(BS->HandleProtocol, 3, imageHandle, &lipGuid, (void**)&loaded_image);
33 if (EFI_ERROR(status))
34 {
35 return status;
36 }
37
38 status = uefi_call_wrapper(BS->HandleProtocol, 3, loaded_image->DeviceHandle, &fsGuid, (VOID*)&IOVolume);
39 if (EFI_ERROR(status))
40 {
41 return status;
42 }
43
44 status = uefi_call_wrapper(IOVolume->OpenVolume, 2, IOVolume, file);
45 if (EFI_ERROR(status))
46 {
47 return status;
48 }
49
50 return EFI_SUCCESS;
51}
52
53static void* rsdp_get(EFI_SYSTEM_TABLE* systemTable)
54{
55 Print(L"Searching for RSDP... ");
56 EFI_CONFIGURATION_TABLE* configTable = systemTable->ConfigurationTable;
57 EFI_GUID acpi2TableGuid = ACPI_20_TABLE_GUID;
58
59 void* rsdp = NULL;
60 for (uint64_t i = 0; i < systemTable->NumberOfTableEntries; i++)
61 {
62 if (CompareGuid(&configTable[i].VendorGuid, &acpi2TableGuid) &&
63 CompareMem("RSD PTR ", configTable->VendorTable, 8) == 0)
64 {
65 rsdp = configTable->VendorTable;
66 }
67 configTable++;
68 }
69
70 if (rsdp == NULL)
71 {
72 Print(L"failed to locate rsdp!\n");
73 }
74 else
75 {
76 Print(L"found at %p!\n", rsdp);
77 }
78 return rsdp;
79}
80
81static EFI_STATUS boot_info_populate(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable, boot_info_t* bootInfo)
82{
83 EFI_STATUS status = gop_buffer_init(&bootInfo->gop);
84 if (EFI_ERROR(status))
85 {
86 return status;
87 }
88
89 bootInfo->rsdp = rsdp_get(systemTable);
90 if (bootInfo->rsdp == NULL)
91 {
92 return EFI_NOT_FOUND;
93 }
94
95 bootInfo->runtimeServices = systemTable->RuntimeServices;
96
97 EFI_FILE* rootHandle;
98 status = open_root_volume(&rootHandle, imageHandle);
99 if (EFI_ERROR(status))
100 {
101 Print(L"failed to open root volume (0x%x)!\n", status);
102 return EFI_LOAD_ERROR;
103 }
104
105 status = disk_load(&bootInfo->disk, rootHandle);
106 if (EFI_ERROR(status))
107 {
108 return status;
109 }
110
111 status = kernel_load(&bootInfo->kernel, rootHandle);
112 if (EFI_ERROR(status))
113 {
114 return status;
115 }
116
117 // Memory map retrived when exiting boot services.
118
119 return EFI_SUCCESS;
120}
121
122static EFI_STATUS exit_boot_services(EFI_HANDLE imageHandle, boot_info_t* bootInfo)
123{
124 EFI_STATUS status;
125
126 uint32_t retries = 0;
127 do
128 {
129 Print(L"Exiting boot services (attempt %d)...\n", retries + 1);
130
131 if (retries > 0)
132 {
133 mem_map_deinit(&bootInfo->memory.map);
134 }
135
136 status = mem_map_init(&bootInfo->memory.map);
137 if (EFI_ERROR(status))
138 {
139 Print(L"Failed to initialize memory map (0x%x)!\n", status);
140 return status;
141 }
142
143 status = uefi_call_wrapper(BS->ExitBootServices, 2, imageHandle, bootInfo->memory.map.key);
144 if (EFI_ERROR(status))
145 {
146 if (status == EFI_INVALID_PARAMETER)
147 {
148 retries++;
149 if (retries >= EXIT_BOOT_SERVICES_MAX_RETRY)
150 {
151 Print(L"Too many retries!\n");
152 mem_map_deinit(&bootInfo->memory.map);
153 return EFI_ABORTED;
154 }
155
156 uefi_call_wrapper(BS->Stall, 1, 1000);
157 }
158 else
159 {
160 mem_map_deinit(&bootInfo->memory.map);
161 Print(L"Failed to exit boot services (0x%x)!\n", status);
162 return status;
163 }
164 }
165 } while (status == EFI_INVALID_PARAMETER && retries < EXIT_BOOT_SERVICES_MAX_RETRY);
166
167 mem_page_table_init(&bootInfo->memory.table, &bootInfo->memory.map, &bootInfo->gop, &bootInfo->kernel);
168
169 return EFI_SUCCESS;
170}
171
172EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable)
173{
174 InitializeLib(imageHandle, systemTable);
175
177
178 EFI_STATUS status = mem_init();
179 if (EFI_ERROR(status))
180 {
181 Print(L"Failed to initialize memory (0x%x)!\n", status);
182 return status;
183 }
184
185 boot_info_t* bootInfo = AllocatePool(sizeof(boot_info_t));
186 if (bootInfo == NULL)
187 {
188 Print(L"Failed to allocate boot info!\n");
189 return EFI_OUT_OF_RESOURCES;
190 }
191
192 status = boot_info_populate(imageHandle, systemTable, bootInfo);
193 if (EFI_ERROR(status))
194 {
195 Print(L"Failed to populate boot info (0x%x)!\n", status);
196 return status;
197 }
198
199 status = exit_boot_services(imageHandle, bootInfo);
200 if (EFI_ERROR(status))
201 {
202 Print(L"Failed to exit boot services (0x%x)!\n", status);
203 return status;
204 }
205
206 page_table_load(&bootInfo->memory.table);
207 bootInfo->kernel.entry(bootInfo);
208
209 // We should never end up back here.
210 return EFI_ABORTED;
211}
EFI_STATUS gop_buffer_init(boot_gop_t *buffer)
Definition gop.c:34
#define EXIT_BOOT_SERVICES_MAX_RETRY
Definition main.c:13
static void * rsdp_get(EFI_SYSTEM_TABLE *systemTable)
Definition main.c:53
static void splash_screen(void)
Definition main.c:15
EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
Definition main.c:172
static EFI_STATUS boot_info_populate(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable, boot_info_t *bootInfo)
Definition main.c:81
static EFI_STATUS open_root_volume(EFI_FILE **file, EFI_HANDLE imageHandle)
Definition main.c:25
static EFI_STATUS exit_boot_services(EFI_HANDLE imageHandle, boot_info_t *bootInfo)
Definition main.c:122
EFI_STATUS disk_load(boot_disk_t *disk, EFI_FILE *rootHandle)
Definition disk.c:203
EFI_STATUS mem_map_init(boot_memory_map_t *map)
Initialize and load the memory map provided by the UEFI firmware.
Definition mem.c:64
void mem_page_table_init(page_table_t *table, boot_memory_map_t *map, boot_gop_t *gop, boot_kernel_t *kernel)
Initializes a page table for use by the kernel.
Definition mem.c:125
void mem_map_deinit(boot_memory_map_t *map)
Deinitializes the memory map and frees any allocated resources.
Definition mem.c:83
EFI_STATUS mem_init(void)
Initializes the basic memory allocator.
Definition mem.c:22
static void page_table_load(page_table_t *table)
Loads the page table into the CR3 register if it is not already loaded.
Definition paging.h:183
#define NULL
Pointer error value.
Definition NULL.h:23
EFI_STATUS kernel_load(boot_kernel_t *kernel, EFI_FILE *rootHandle)
Definition kernel.c:298
static dentry_t * file
Definition log_file.c:17
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
boot_memory_t memory
Definition boot_info.h:107
void * runtimeServices
Definition boot_info.h:104
boot_disk_t disk
Definition boot_info.h:105
boot_gop_t gop
Definition boot_info.h:102
void * rsdp
Definition boot_info.h:103
boot_kernel_t kernel
Definition boot_info.h:106
void(* entry)(boot_info_t *)
Definition boot_info.h:90
page_table_t table
Definition boot_info.h:97
boot_memory_map_t map
Definition boot_info.h:96