bootloader.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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
  112. VOID *buffer = NULL;
  113. status = uefi_call_wrapper(
  114. SystemTable->BootServices->AllocatePool,
  115. 3,
  116. EfiLoaderData,
  117. file_size,
  118. &buffer
  119. );
  120. if (EFI_ERROR(status)) {
  121. uefi_call_wrapper(file->Close, 1, file);
  122. uefi_call_wrapper(root->Close, 1, root);
  123. return status;
  124. }
  125. // 7. Read file contents
  126. UINTN read_size = file_size;
  127. status = uefi_call_wrapper(file->Read, 3, file, &read_size, buffer);
  128. if (EFI_ERROR(status) || read_size != file_size) {
  129. uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, buffer);
  130. uefi_call_wrapper(file->Close, 1, file);
  131. uefi_call_wrapper(root->Close, 1, root);
  132. return EFI_DEVICE_ERROR;
  133. }
  134. // 8. Clean up and return
  135. uefi_call_wrapper(file->Close, 1, file);
  136. uefi_call_wrapper(root->Close, 1, root);
  137. *BufferOut = buffer;
  138. *SizeOut = file_size;
  139. return EFI_SUCCESS;
  140. }
  141. EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
  142. InitializeLib(ImageHandle, SystemTable);
  143. EFI_STATUS status;
  144. // 1. Locate the Graphics Output Protocol (GOP)
  145. EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
  146. EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
  147. status = uefi_call_wrapper(
  148. SystemTable->BootServices->LocateProtocol,
  149. 3,
  150. &gop_guid,
  151. NULL,
  152. (VOID **)&gop
  153. );
  154. UINTN center_x = 0;
  155. UINTN center_y = 0;
  156. UINTN anim_width = 200;
  157. UINTN anim_height = 200;
  158. // 2. Clear screen to black and display the white dot
  159. if (!EFI_ERROR(status) && gop) {
  160. EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
  161. uefi_call_wrapper(
  162. gop->Blt,
  163. 10,
  164. gop,
  165. &black,
  166. EfiBltVideoFill,
  167. 0, 0,
  168. 0, 0,
  169. gop->Mode->Info->HorizontalResolution,
  170. gop->Mode->Info->VerticalResolution,
  171. 0
  172. );
  173. center_x = (gop->Mode->Info->HorizontalResolution - anim_width) / 2;
  174. center_y = (gop->Mode->Info->VerticalResolution - anim_height) / 2;
  175. // Draw a 6x6 pixel white dot in the center of the 200x200 region
  176. EFI_GRAPHICS_OUTPUT_BLT_PIXEL white = {255, 255, 255, 0};
  177. uefi_call_wrapper(
  178. gop->Blt,
  179. 10,
  180. gop,
  181. &white,
  182. EfiBltVideoFill,
  183. 0, 0,
  184. center_x + 97, center_y + 97,
  185. 6, 6,
  186. 0
  187. );
  188. }
  189. // 3. Perform OS Key signature check and load DRM
  190. status = check_os_signature(ImageHandle, SystemTable);
  191. if (EFI_ERROR(status)) {
  192. return status;
  193. }
  194. load_drm_module();
  195. // 4. Resolve path and load the kernel image (bzImage)
  196. EFI_LOADED_IMAGE *loaded_image = NULL;
  197. status = uefi_call_wrapper(
  198. SystemTable->BootServices->HandleProtocol,
  199. 3,
  200. ImageHandle,
  201. &LoadedImageProtocol,
  202. (VOID **)&loaded_image
  203. );
  204. if (EFI_ERROR(status)) return status;
  205. EFI_DEVICE_PATH *kernel_path = FileDevicePath(loaded_image->DeviceHandle, L"\\EFI\\BOOT\\bzImage");
  206. if (kernel_path == NULL) return EFI_OUT_OF_RESOURCES;
  207. EFI_HANDLE kernel_img = NULL;
  208. status = uefi_call_wrapper(
  209. SystemTable->BootServices->LoadImage,
  210. 6,
  211. FALSE,
  212. ImageHandle,
  213. kernel_path,
  214. NULL,
  215. 0,
  216. &kernel_img
  217. );
  218. if (EFI_ERROR(status)) return status;
  219. // 5. Play the boot animation (expanding nucleus) from ESP
  220. if (gop) {
  221. VOID *anim_buffer = NULL;
  222. UINTN anim_size = 0;
  223. status = read_file_from_esp(ImageHandle, SystemTable, L"\\EFI\\BOOT\\animation.bin", &anim_buffer, &anim_size);
  224. if (!EFI_ERROR(status)) {
  225. UINTN num_frames = 60;
  226. UINTN expected_size = num_frames * anim_width * anim_height * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
  227. if (anim_size >= expected_size) {
  228. // Clear the white dot to black first
  229. EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
  230. uefi_call_wrapper(
  231. gop->Blt,
  232. 10,
  233. gop,
  234. &black,
  235. EfiBltVideoFill,
  236. 0, 0,
  237. 0, 0,
  238. gop->Mode->Info->HorizontalResolution,
  239. gop->Mode->Info->VerticalResolution,
  240. 0
  241. );
  242. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *frames = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)anim_buffer;
  243. for (UINTN f = 0; f < num_frames; f++) {
  244. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *frame = &frames[f * anim_width * anim_height];
  245. uefi_call_wrapper(
  246. gop->Blt,
  247. 10,
  248. gop,
  249. frame,
  250. EfiBltBufferToVideo,
  251. 0, 0,
  252. center_x, center_y,
  253. anim_width, anim_height,
  254. anim_width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
  255. );
  256. uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 16666);
  257. }
  258. }
  259. uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, anim_buffer);
  260. }
  261. }
  262. // 6. Set command line options for the kernel
  263. EFI_LOADED_IMAGE *kernel_loaded_image = NULL;
  264. status = uefi_call_wrapper(
  265. SystemTable->BootServices->HandleProtocol,
  266. 3,
  267. kernel_img,
  268. &LoadedImageProtocol,
  269. (VOID **)&kernel_loaded_image
  270. );
  271. if (EFI_ERROR(status)) return status;
  272. CHAR16 *cmd_line = L"initrd=\\EFI\\BOOT\\initramfs.img console=ttyS0 loglevel=0 logo.nologo init=/init root=/dev/sdb rw quiet vt.global_cursor_default=0";
  273. kernel_loaded_image->LoadOptions = cmd_line;
  274. kernel_loaded_image->LoadOptionsSize = (StrLen(cmd_line) + 1) * sizeof(CHAR16);
  275. // 7. Start the kernel
  276. UINTN exit_data_size = 0;
  277. CHAR16 *exit_data = NULL;
  278. status = uefi_call_wrapper(
  279. SystemTable->BootServices->StartImage,
  280. 3,
  281. kernel_img,
  282. &exit_data_size,
  283. &exit_data
  284. );
  285. return status;
  286. }