diff options
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 114 |
1 files changed, 114 insertions, 0 deletions
| @@ -0,0 +1,114 @@ | |||
| 1 | /* ============================================================================= | ||
| 2 | * main.c — RNG UEFI bootloader (rsbl) — minimal smoke-test version | ||
| 3 | * | ||
| 4 | * Just prints to screen then loads kernel + initrd via LoadImage/StartImage. | ||
| 5 | * ============================================================================= */ | ||
| 6 | |||
| 7 | #include "uefi.h" | ||
| 8 | |||
| 9 | static const char16 kpath[] = u"\\bzImage"; | ||
| 10 | static const char16 ipath[] = u"\\initramfs.cpio.gz"; | ||
| 11 | /* same cmdline systemd-boot used */ | ||
| 12 | static const char16 base_opt[] = u"console=ttyS0,115200 console=tty0 earlyprintk=serial,ttyS0,115200 loglevel=3 rng_tty=ttyS0 initrd=\\initramfs.cpio.gz"; | ||
| 13 | |||
| 14 | static efi_guid lg = EFI_LOADED_IMAGE_GUID; | ||
| 15 | static efi_guid sg = EFI_SIMPLE_FILE_SYSTEM_GUID; | ||
| 16 | |||
| 17 | static void pr(efi_simple_text_output *c, const char16 *s) { c->output_string(c, s); } | ||
| 18 | static void ph(efi_simple_text_output *c, u64 v) { | ||
| 19 | char16 b[19] = u"0x0000000000000000"; | ||
| 20 | for (int i = 17; i >= 2; i--) { | ||
| 21 | u8 n = (u8)(v & 0xF); | ||
| 22 | b[i] = n < 10 ? u'0' + n : u'a' + n - 10; | ||
| 23 | v >>= 4; | ||
| 24 | } | ||
| 25 | c->output_string(c, b); | ||
| 26 | } | ||
| 27 | |||
| 28 | static u64 allocate_pages(efi_boot_services *b, u64 mt, u64 np, u64 *a) { | ||
| 29 | typedef u64 (*F)(u64, u64, u64, u64 *); | ||
| 30 | return ((F)b->allocate_pages)(0, mt, np, a); | ||
| 31 | } | ||
| 32 | static u8 *rf(efi_boot_services *b, efi_file_protocol *f, u64 *sz, u64 mx) { | ||
| 33 | u64 np = (mx + 4095) / 4096, a; | ||
| 34 | if (allocate_pages(b, 6, np, &a)) return 0; | ||
| 35 | u8 *d = (u8 *)a; | ||
| 36 | u64 r = mx; | ||
| 37 | if (f->read(f, &r, d) && r != mx) return 0; | ||
| 38 | *sz = r; return d; | ||
| 39 | } | ||
| 40 | |||
| 41 | u64 __attribute__((aligned(16))) efi_main(handle ih, efi_system_table *st) { | ||
| 42 | efi_simple_text_output *c = st->con_out; | ||
| 43 | efi_boot_services *b = st->boot_services; | ||
| 44 | u64 s; | ||
| 45 | |||
| 46 | pr(c, u"\r\n"); | ||
| 47 | pr(c, u"rsbl v0.1 -- RNG UEFI Bootloader\r\n"); | ||
| 48 | pr(c, u"\r\n"); | ||
| 49 | |||
| 50 | efi_loaded_image *our_li; | ||
| 51 | s = b->handle_protocol(ih, &lg, (void **)&our_li); | ||
| 52 | if (s) { pr(c, u" handle_protocol LI failed\r\n"); goto h; } | ||
| 53 | |||
| 54 | efi_simple_file_system *fs; | ||
| 55 | s = b->handle_protocol(our_li->device_handle, &sg, (void **)&fs); | ||
| 56 | if (s) { pr(c, u" SFSP not on device handle\r\n"); goto h; } | ||
| 57 | |||
| 58 | efi_file_protocol *rt; | ||
| 59 | s = fs->open_volume(fs, (void **)&rt); | ||
| 60 | if (s) { pr(c, u" open_volume failed\r\n"); goto h; } | ||
| 61 | |||
| 62 | pr(c, u" [ loading kernel\r"); | ||
| 63 | efi_file_protocol *f; | ||
| 64 | s = rt->open(rt, &f, (char16 *)kpath, 1, 0); | ||
| 65 | if (s) { pr(c, u" [FAIL] loading kernel\r\n"); goto h; } | ||
| 66 | u64 ks; u8 *kd = rf(b, f, &ks, 64*1024*1024); | ||
| 67 | f->close(f); | ||
| 68 | if (!kd) { pr(c, u" [FAIL] loading kernel\r\n"); goto h; } | ||
| 69 | pr(c, u" [ ok] loading kernel "); ph(c, ks); pr(c, u" bytes\r\n"); | ||
| 70 | |||
| 71 | pr(c, u" [ loading initrd\r"); | ||
| 72 | s = rt->open(rt, &f, (char16 *)ipath, 1, 0); | ||
| 73 | if (s) { pr(c, u" [FAIL] loading initrd\r\n"); goto h; } | ||
| 74 | u64 is; u8 *id = rf(b, f, &is, 32*1024*1024); | ||
| 75 | f->close(f); | ||
| 76 | if (!id) { pr(c, u" [FAIL] loading initrd\r\n"); goto h; } | ||
| 77 | pr(c, u" [ ok] loading initrd "); ph(c, is); pr(c, u" bytes\r\n"); | ||
| 78 | |||
| 79 | pr(c, u" [ starting image\r"); | ||
| 80 | handle kh = 0; | ||
| 81 | s = b->load_image(0, ih, 0, kd, ks, &kh); | ||
| 82 | if (s) { pr(c, u" [FAIL] LoadImage\r\n"); goto h; } | ||
| 83 | |||
| 84 | efi_loaded_image *kli; | ||
| 85 | s = b->handle_protocol(kh, &lg, (void **)&kli); | ||
| 86 | if (s) { pr(c, u" [FAIL] kernel image info\r\n"); goto h; } | ||
| 87 | kli->device_handle = our_li->device_handle; | ||
| 88 | |||
| 89 | u16 osz = 0; | ||
| 90 | while (base_opt[osz]) osz++; | ||
| 91 | osz = (osz + 1) * 2; | ||
| 92 | u16 *opts; | ||
| 93 | { | ||
| 94 | typedef u64 (*ap_t)(u8, u64, void **); | ||
| 95 | s = ((ap_t)b->allocate_pool)(0, osz, (void **)&opts); | ||
| 96 | } | ||
| 97 | if (s) { pr(c, u" [FAIL] cmdline alloc\r\n"); goto h; } | ||
| 98 | for (u16 i = 0; i < osz / 2; i++) opts[i] = base_opt[i]; | ||
| 99 | kli->load_options = opts; | ||
| 100 | kli->load_options_size = osz; | ||
| 101 | |||
| 102 | pr(c, u" [ ok] starting image\r\n"); | ||
| 103 | pr(c, u"\r\n"); | ||
| 104 | pr(c, u" Launching RNG/Linux ...\r\n"); | ||
| 105 | pr(c, u"\r\n"); | ||
| 106 | |||
| 107 | s = b->start_image(kh, 0, 0); | ||
| 108 | pr(c, u" kernel returned "); ph(c, s); pr(c, u"\r\n"); | ||
| 109 | |||
| 110 | h: | ||
| 111 | pr(c, u" Halt\r\n"); | ||
| 112 | while (1) asm volatile("hlt"); | ||
| 113 | return s; | ||
| 114 | } | ||
