bootloader.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. #include <efi.h>
  2. #include <efilib.h>
  3. // Simulated hardware secure key
  4. #define HARDWARE_SECURE_KEY "ARK-OS-9aaafa37077ee91e5df2f47a8e9e1564beecde1cc13b279f51d915bf8c746eb4"
  5. EFI_STATUS check_os_signature(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
  6. // Conceptual hardware verified boot check
  7. int has_key = 1;
  8. int match = 1;
  9. if (has_key) {
  10. if (match) {
  11. return EFI_SUCCESS;
  12. } else {
  13. return EFI_SECURITY_VIOLATION;
  14. }
  15. } else {
  16. return EFI_SUCCESS;
  17. }
  18. }
  19. EFI_STATUS load_drm_module() {
  20. // Conceptual DRM module loading
  21. return EFI_SUCCESS;
  22. }
  23. static EFI_STATUS read_file_from_esp(
  24. EFI_HANDLE ImageHandle,
  25. EFI_SYSTEM_TABLE *SystemTable,
  26. CHAR16 *FileName,
  27. VOID **BufferOut,
  28. UINTN *SizeOut
  29. ) {
  30. EFI_STATUS status;
  31. EFI_LOADED_IMAGE *loaded_image = NULL;
  32. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs = NULL;
  33. EFI_FILE_HANDLE root = NULL;
  34. EFI_FILE_HANDLE file = NULL;
  35. // 1. Get the LoadedImage protocol for the current bootloader
  36. status = uefi_call_wrapper(
  37. SystemTable->BootServices->HandleProtocol,
  38. 3,
  39. ImageHandle,
  40. &LoadedImageProtocol,
  41. (VOID **)&loaded_image
  42. );
  43. if (EFI_ERROR(status)) return status;
  44. // 2. Open the SimpleFileSystem protocol on the device handle of the loaded image
  45. status = uefi_call_wrapper(
  46. SystemTable->BootServices->HandleProtocol,
  47. 3,
  48. loaded_image->DeviceHandle,
  49. &FileSystemProtocol,
  50. (VOID **)&fs
  51. );
  52. if (EFI_ERROR(status)) return status;
  53. // 3. Open the volume
  54. status = uefi_call_wrapper(fs->OpenVolume, 2, fs, &root);
  55. if (EFI_ERROR(status)) return status;
  56. // 4. Open the file
  57. status = uefi_call_wrapper(
  58. root->Open,
  59. 5,
  60. root,
  61. &file,
  62. FileName,
  63. EFI_FILE_MODE_READ,
  64. 0
  65. );
  66. if (EFI_ERROR(status)) {
  67. uefi_call_wrapper(root->Close, 1, root);
  68. return status;
  69. }
  70. // 5. Get file info to determine size
  71. EFI_FILE_INFO *file_info = NULL;
  72. UINTN info_size = 0;
  73. status = uefi_call_wrapper(
  74. file->GetInfo,
  75. 4,
  76. file,
  77. &GenericFileInfo,
  78. &info_size,
  79. NULL
  80. );
  81. if (status == EFI_BUFFER_TOO_SMALL) {
  82. status = uefi_call_wrapper(
  83. SystemTable->BootServices->AllocatePool,
  84. 3,
  85. EfiLoaderData,
  86. info_size,
  87. (VOID **)&file_info
  88. );
  89. if (EFI_ERROR(status)) {
  90. uefi_call_wrapper(file->Close, 1, file);
  91. uefi_call_wrapper(root->Close, 1, root);
  92. return status;
  93. }
  94. status = uefi_call_wrapper(
  95. file->GetInfo,
  96. 4,
  97. file,
  98. &GenericFileInfo,
  99. &info_size,
  100. (VOID *)file_info
  101. );
  102. }
  103. if (EFI_ERROR(status)) {
  104. if (file_info) uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, file_info);
  105. uefi_call_wrapper(file->Close, 1, file);
  106. uefi_call_wrapper(root->Close, 1, root);
  107. return status;
  108. }
  109. UINTN file_size = file_info->FileSize;
  110. uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, file_info);
  111. // 6. Allocate buffer for file contents using AllocatePages for large buffers
  112. UINTN num_pages = (file_size + 4095) / 4096;
  113. EFI_PHYSICAL_ADDRESS phys_buffer = 0;
  114. status = uefi_call_wrapper(
  115. SystemTable->BootServices->AllocatePages,
  116. 4,
  117. AllocateAnyPages,
  118. EfiLoaderData,
  119. num_pages,
  120. &phys_buffer
  121. );
  122. if (EFI_ERROR(status)) {
  123. uefi_call_wrapper(file->Close, 1, file);
  124. uefi_call_wrapper(root->Close, 1, root);
  125. return status;
  126. }
  127. VOID *buffer = (VOID *)(UINTN)phys_buffer;
  128. // 7. Read file contents
  129. UINTN read_size = file_size;
  130. status = uefi_call_wrapper(file->Read, 3, file, &read_size, buffer);
  131. if (EFI_ERROR(status) || read_size != file_size) {
  132. uefi_call_wrapper(SystemTable->BootServices->FreePages, 2, phys_buffer, num_pages);
  133. uefi_call_wrapper(file->Close, 1, file);
  134. uefi_call_wrapper(root->Close, 1, root);
  135. return EFI_DEVICE_ERROR;
  136. }
  137. // 8. Clean up and return
  138. uefi_call_wrapper(file->Close, 1, file);
  139. uefi_call_wrapper(root->Close, 1, root);
  140. *BufferOut = buffer;
  141. *SizeOut = file_size;
  142. return EFI_SUCCESS;
  143. }
  144. EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
  145. InitializeLib(ImageHandle, SystemTable);
  146. EFI_STATUS status;
  147. // 1. Locate the Graphics Output Protocol (GOP)
  148. EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
  149. EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
  150. status = uefi_call_wrapper(
  151. SystemTable->BootServices->LocateProtocol,
  152. 3,
  153. &gop_guid,
  154. NULL,
  155. (VOID **)&gop
  156. );
  157. UINTN center_x = 0;
  158. UINTN center_y = 0;
  159. UINTN anim_width = 200;
  160. UINTN anim_height = 200;
  161. // 2. Clear screen to black and display the white dot
  162. if (!EFI_ERROR(status) && gop) {
  163. EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
  164. uefi_call_wrapper(
  165. gop->Blt,
  166. 10,
  167. gop,
  168. &black,
  169. EfiBltVideoFill,
  170. 0, 0,
  171. 0, 0,
  172. gop->Mode->Info->HorizontalResolution,
  173. gop->Mode->Info->VerticalResolution,
  174. 0
  175. );
  176. center_x = (gop->Mode->Info->HorizontalResolution - anim_width) / 2;
  177. center_y = (gop->Mode->Info->VerticalResolution - anim_height) / 2;
  178. // Draw a 6x6 pixel white dot in the center of the 200x200 region
  179. EFI_GRAPHICS_OUTPUT_BLT_PIXEL white = {255, 255, 255, 0};
  180. uefi_call_wrapper(
  181. gop->Blt,
  182. 10,
  183. gop,
  184. &white,
  185. EfiBltVideoFill,
  186. 0, 0,
  187. center_x + 97, center_y + 97,
  188. 6, 6,
  189. 0
  190. );
  191. }
  192. // 3. Perform OS Key signature check and load DRM
  193. status = check_os_signature(ImageHandle, SystemTable);
  194. if (EFI_ERROR(status)) {
  195. return status;
  196. }
  197. load_drm_module();
  198. // 4. Resolve path and load the kernel image (bzImage)
  199. EFI_LOADED_IMAGE *loaded_image = NULL;
  200. status = uefi_call_wrapper(
  201. SystemTable->BootServices->HandleProtocol,
  202. 3,
  203. ImageHandle,
  204. &LoadedImageProtocol,
  205. (VOID **)&loaded_image
  206. );
  207. if (EFI_ERROR(status)) return status;
  208. EFI_DEVICE_PATH *kernel_path = FileDevicePath(loaded_image->DeviceHandle, L"\\EFI\\BOOT\\bzImage");
  209. if (kernel_path == NULL) return EFI_OUT_OF_RESOURCES;
  210. EFI_HANDLE kernel_img = NULL;
  211. status = uefi_call_wrapper(
  212. SystemTable->BootServices->LoadImage,
  213. 6,
  214. FALSE,
  215. ImageHandle,
  216. kernel_path,
  217. NULL,
  218. 0,
  219. &kernel_img
  220. );
  221. if (EFI_ERROR(status)) return status;
  222. // 5. Play the boot animation (expanding nucleus) from ESP
  223. if (gop) {
  224. VOID *anim_buffer = NULL;
  225. UINTN anim_size = 0;
  226. status = read_file_from_esp(ImageHandle, SystemTable, L"\\EFI\\BOOT\\animation.bin", &anim_buffer, &anim_size);
  227. if (EFI_ERROR(status)) {
  228. EFI_GRAPHICS_OUTPUT_BLT_PIXEL red = {0, 0, 255, 0};
  229. uefi_call_wrapper(gop->Blt, 10, gop, &red, EfiBltVideoFill, 0, 0, center_x + 97, center_y + 97, 16, 16, 0);
  230. uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 3000000); // 3 seconds
  231. } else {
  232. UINTN num_frames = 60;
  233. UINTN expected_size = num_frames * anim_width * anim_height * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
  234. if (anim_size < expected_size) {
  235. EFI_GRAPHICS_OUTPUT_BLT_PIXEL green = {0, 255, 0, 0};
  236. uefi_call_wrapper(gop->Blt, 10, gop, &green, EfiBltVideoFill, 0, 0, center_x + 97, center_y + 97, 16, 16, 0);
  237. uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 3000000); // 3 seconds
  238. } else {
  239. // Clear the white dot to black first
  240. EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
  241. uefi_call_wrapper(
  242. gop->Blt,
  243. 10,
  244. gop,
  245. &black,
  246. EfiBltVideoFill,
  247. 0, 0,
  248. 0, 0,
  249. gop->Mode->Info->HorizontalResolution,
  250. gop->Mode->Info->VerticalResolution,
  251. 0
  252. );
  253. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *frames = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)anim_buffer;
  254. for (UINTN f = 0; f < num_frames; f++) {
  255. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *frame = &frames[f * anim_width * anim_height];
  256. uefi_call_wrapper(
  257. gop->Blt,
  258. 10,
  259. gop,
  260. frame,
  261. EfiBltBufferToVideo,
  262. 0, 0,
  263. center_x, center_y,
  264. anim_width, anim_height,
  265. anim_width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
  266. );
  267. uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 16666);
  268. }
  269. }
  270. uefi_call_wrapper(SystemTable->BootServices->FreePages, 2, (EFI_PHYSICAL_ADDRESS)(UINTN)anim_buffer, (anim_size + 4095) / 4096);
  271. }
  272. }
  273. // 6. Set command line options for the kernel
  274. EFI_LOADED_IMAGE *kernel_loaded_image = NULL;
  275. status = uefi_call_wrapper(
  276. SystemTable->BootServices->HandleProtocol,
  277. 3,
  278. kernel_img,
  279. &LoadedImageProtocol,
  280. (VOID **)&kernel_loaded_image
  281. );
  282. if (EFI_ERROR(status)) return status;
  283. CHAR16 *cmd_line = L"initrd=\\EFI\\BOOT\\initramfs.img console=ttyS0 console=tty0 loglevel=0 logo.nologo init=/init root=/dev/sdb rw quiet vt.global_cursor_default=0";
  284. kernel_loaded_image->LoadOptions = cmd_line;
  285. kernel_loaded_image->LoadOptionsSize = (StrLen(cmd_line) + 1) * sizeof(CHAR16);
  286. // 7. Start the kernel
  287. UINTN exit_data_size = 0;
  288. CHAR16 *exit_data = NULL;
  289. status = uefi_call_wrapper(
  290. SystemTable->BootServices->StartImage,
  291. 3,
  292. kernel_img,
  293. &exit_data_size,
  294. &exit_data
  295. );
  296. return status;
  297. }