moremultiboot.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. static mboot_mod_t modules_mboot[sizeof(modules)/sizeof(*modules)] = {
  2. {0,0,0,1}
  3. };
  4. static struct multiboot multiboot_header = {
  5. /* flags; */ MULTIBOOT_FLAG_CMDLINE | MULTIBOOT_FLAG_MODS | MULTIBOOT_FLAG_MEM | MULTIBOOT_FLAG_MMAP | MULTIBOOT_FLAG_LOADER,
  6. /* mem_lower; */ 0x100000,
  7. /* mem_upper; */ 0x640000,
  8. /* boot_device; */ 0,
  9. /* cmdline; */ 0,
  10. /* mods_count; */ sizeof(modules)/sizeof(*modules),
  11. /* mods_addr; */ 0,
  12. /* num; */ 0,
  13. /* size; */ 0,
  14. /* addr; */ 0,
  15. /* shndx; */ 0,
  16. /* mmap_length; */ 0,
  17. /* mmap_addr; */ 0,
  18. /* drives_length; */ 0,
  19. /* drives_addr; */ 0,
  20. /* config_table; */ 0,
  21. /* boot_loader_name; */ 0,
  22. /* apm_table; */ 0,
  23. /* vbe_control_info; */ 0,
  24. /* vbe_mode_info; */ 0,
  25. /* vbe_mode; */ 0,
  26. /* vbe_interface_seg; */ 0,
  27. /* vbe_interface_off; */ 0,
  28. /* vbe_interface_len; */ 0,
  29. };
  30. static long ramdisk_off = 1;
  31. static long ramdisk_len = 1;
  32. int _eax = 1;
  33. int _ebx = 1;
  34. int _xmain = 1;
  35. struct mmap_entry {
  36. uint64_t base;
  37. uint64_t len;
  38. uint32_t type;
  39. uint32_t reserved;
  40. };
  41. extern unsigned short mmap_ent;
  42. extern unsigned short lower_mem;
  43. char * final_offset = NULL;
  44. extern char do_the_nasty[];
  45. static int strlen(char * s) {
  46. int out = 0;
  47. while (*s) {
  48. s++;
  49. out++;
  50. }
  51. return out;
  52. }
  53. #ifdef EFI_PLATFORM
  54. static EFI_GUID efi_graphics_output_protocol_guid =
  55. {0x9042a9de,0x23dc,0x4a38, {0x96,0xfb,0x7a,0xde,0xd0,0x80,0x51,0x6a}};
  56. #endif
  57. static void move_kernel(void) {
  58. clear();
  59. print("Relocating kernel...\n");
  60. Elf32_Header * header = (Elf32_Header *)KERNEL_LOAD_START;
  61. if (header->e_ident[0] != ELFMAG0 ||
  62. header->e_ident[1] != ELFMAG1 ||
  63. header->e_ident[2] != ELFMAG2 ||
  64. header->e_ident[3] != ELFMAG3) {
  65. print("Kernel is invalid?\n");
  66. }
  67. uintptr_t entry = (uintptr_t)header->e_entry;
  68. for (uintptr_t x = 0; x < (uint32_t)header->e_phentsize * header->e_phnum; x += header->e_phentsize) {
  69. Elf32_Phdr * phdr = (Elf32_Phdr *)((uint8_t*)KERNEL_LOAD_START + header->e_phoff + x);
  70. if (phdr->p_type == PT_LOAD) {
  71. //read_fs(file, phdr->p_offset, phdr->p_filesz, (uint8_t *)phdr->p_vaddr);
  72. print("Loading a Phdr... ");
  73. print_hex(phdr->p_vaddr);
  74. print(" ");
  75. print_hex(phdr->p_offset);
  76. print(" ");
  77. print_hex(phdr->p_filesz);
  78. print("\n");
  79. #ifdef EFI_PLATFORM
  80. EFI_PHYSICAL_ADDRESS addr = phdr->p_vaddr;
  81. uefi_call_wrapper(ST->BootServices->AllocatePages, 3, AllocateAddress, 0x80000000, phdr->p_memsz / 4096 + 1, &addr);
  82. #endif
  83. memcpy((uint8_t*)(uintptr_t)phdr->p_vaddr, (uint8_t*)KERNEL_LOAD_START + phdr->p_offset, phdr->p_filesz);
  84. long r = phdr->p_filesz;
  85. while (r < phdr->p_memsz) {
  86. *(char *)(phdr->p_vaddr + r) = 0;
  87. r++;
  88. }
  89. }
  90. }
  91. print("Setting up memory map...\n");
  92. #ifdef EFI_PLATFORM
  93. mboot_memmap_t * mmap = (void*)KERNEL_LOAD_START;
  94. memset((void*)KERNEL_LOAD_START, 0x00, 1024);
  95. multiboot_header.mmap_addr = (uintptr_t)mmap;
  96. EFI_STATUS e;
  97. UINTN mapSize = 0, mapKey, descriptorSize;
  98. UINT32 descriptorVersion;
  99. e = uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, NULL, &mapKey, &descriptorSize, NULL);
  100. print_("Memory map size is "); print_hex_(mapSize); print_("\n");
  101. EFI_MEMORY_DESCRIPTOR * efi_memory = (void*)(final_offset);
  102. final_offset += mapSize;
  103. while ((uintptr_t)final_offset & 0x3ff) final_offset++;
  104. e = uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, efi_memory, &mapKey, &descriptorSize, NULL);
  105. if (EFI_ERROR(e)) {
  106. print_("EFI error.\n");
  107. }
  108. uint64_t upper_mem = 0;
  109. int descriptors = mapSize / descriptorSize;
  110. for (int i = 0; i < descriptors; ++i) {
  111. EFI_MEMORY_DESCRIPTOR * d = efi_memory;
  112. mmap->size = sizeof(uint64_t) * 2 + sizeof(uintptr_t);
  113. mmap->base_addr = d->PhysicalStart;
  114. mmap->length = d->NumberOfPages * 4096;
  115. switch (d->Type) {
  116. case EfiConventionalMemory:
  117. case EfiLoaderCode:
  118. case EfiLoaderData:
  119. case EfiBootServicesCode:
  120. case EfiBootServicesData:
  121. case EfiRuntimeServicesCode:
  122. case EfiRuntimeServicesData:
  123. case EfiACPIReclaimMemory:
  124. mmap->type = 1;
  125. break;
  126. case EfiReservedMemoryType:
  127. case EfiUnusableMemory:
  128. case EfiMemoryMappedIO:
  129. case EfiMemoryMappedIOPortSpace:
  130. case EfiPalCode:
  131. case EfiACPIMemoryNVS:
  132. default:
  133. mmap->type = 2;
  134. break;
  135. }
  136. if (mmap->type == 1 && mmap->base_addr >= 0x100000) {
  137. upper_mem += mmap->length;
  138. }
  139. mmap = (mboot_memmap_t *) ((uintptr_t)mmap + mmap->size + sizeof(uintptr_t));
  140. efi_memory = (EFI_MEMORY_DESCRIPTOR *)((char *)efi_memory + descriptorSize);
  141. }
  142. multiboot_header.mem_lower = 1024;
  143. multiboot_header.mem_upper = upper_mem / 1024;
  144. /* Set up framebuffer */
  145. if (_efi_do_mode_set) {
  146. UINTN count;
  147. EFI_HANDLE * handles;
  148. EFI_GRAPHICS_OUTPUT_PROTOCOL * gfx;
  149. EFI_STATUS status;
  150. status = uefi_call_wrapper(ST->BootServices->LocateHandleBuffer,
  151. 5, ByProtocol, &efi_graphics_output_protocol_guid, NULL, &count, &handles);
  152. if (EFI_ERROR(status)) {
  153. print_("Error getting graphics device handle.\n");
  154. while (1) {};
  155. }
  156. status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
  157. 3, handles[0], &efi_graphics_output_protocol_guid, (void **)&gfx);
  158. if (EFI_ERROR(status)) {
  159. print_("Error getting graphics device.\n");
  160. while (1) {};
  161. }
  162. #if 0
  163. print_("Attempting to set a sane mode (32bit color, etc.)\n");
  164. print_("There are 0x"); print_hex_(gfx->Mode->MaxMode); print_(" modes available.\n");
  165. print_("This is mode 0x"); print_hex_(gfx->Mode->Mode); print_(".\n");
  166. #endif
  167. int biggest = gfx->Mode->Mode;
  168. int big_width = 0;
  169. int big_height = 0;
  170. clear_();
  171. for (int i = 0; i < gfx->Mode->MaxMode; ++i) {
  172. EFI_STATUS status;
  173. UINTN size;
  174. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * info;
  175. status = uefi_call_wrapper(gfx->QueryMode,
  176. 4, gfx, i, &size, &info);
  177. if (EFI_ERROR(status)) {
  178. print_("Error getting gfx mode 0x"); print_hex_(i); print_("\n");
  179. } else {
  180. print_("Mode "); print_int_(i); print_(" "); print_int_(info->HorizontalResolution);
  181. print_("x"); print_int_(info->VerticalResolution); print_(" ");
  182. print_int_(info->PixelFormat); print_("\n");
  183. if (_efi_do_mode_set == 1) {
  184. if (info->PixelFormat == 1 && info->HorizontalResolution >= big_width) {
  185. biggest = i;
  186. big_width = info->HorizontalResolution;
  187. }
  188. } else if (_efi_do_mode_set == 2) {
  189. if (info->PixelFormat == 1 && info->HorizontalResolution == 1024 &&
  190. info->VerticalResolution == 768) {
  191. biggest = i;
  192. break;
  193. }
  194. } else if (_efi_do_mode_set == 3) {
  195. if (info->PixelFormat == 1 && info->HorizontalResolution == 1920 &&
  196. info->VerticalResolution == 1080) {
  197. biggest = i;
  198. break;
  199. }
  200. } else if (_efi_do_mode_set == 4) {
  201. while (1) {
  202. print_("y/n? ");
  203. int resp = read_scancode();
  204. if (resp == 'y') {
  205. print_("y\n");
  206. biggest = i;
  207. goto done_video;
  208. } else if (resp == 'n') {
  209. print_("n\n");
  210. break;
  211. }
  212. print_("?\n");
  213. }
  214. }
  215. }
  216. }
  217. done_video:
  218. print_("Selected video mode was "); print_int_(biggest); print_("\n");
  219. uefi_call_wrapper(gfx->SetMode, 2, gfx, biggest);
  220. uint32_t high = gfx->Mode->FrameBufferBase >> 32;
  221. uint32_t low = gfx->Mode->FrameBufferBase & 0xFFFFFFFF;
  222. print_("Framebuffer address is 0x"); print_hex_(high); print_hex_(low); print_("\n");
  223. if (high) {
  224. clear_();
  225. print_("Framebuffer is outside of 32-bit memory range.\n");
  226. print_("EFI mode setting is not available - and graphics may not work in general.\n");
  227. while (1) {};
  228. }
  229. multiboot_header.flags |= (1 << 12); /* Enable framebuffer flag */
  230. multiboot_header.framebuffer_addr = low;
  231. multiboot_header.framebuffer_width = gfx->Mode->Info->HorizontalResolution;
  232. multiboot_header.framebuffer_height = gfx->Mode->Info->VerticalResolution;
  233. multiboot_header.framebuffer_pitch = gfx->Mode->Info->PixelsPerScanLine * 4;
  234. print_("Mode information passed to multiboot:\n");
  235. print_(" Address: 0x"); print_hex_(multiboot_header.framebuffer_addr); print_("\n");
  236. print_(" Width: "); print_int_(multiboot_header.framebuffer_width); print_("\n");
  237. print_(" Height: "); print_int_(multiboot_header.framebuffer_height); print_("\n");
  238. print_("\n");
  239. }
  240. memcpy(final_offset, cmdline, strlen(cmdline)+1);
  241. multiboot_header.cmdline = (uintptr_t)final_offset;
  242. final_offset += strlen(cmdline)+1;
  243. memcpy(final_offset, VERSION_TEXT, strlen(VERSION_TEXT)+1);
  244. multiboot_header.boot_loader_name = (uintptr_t)final_offset;
  245. final_offset += strlen(VERSION_TEXT)+1;
  246. while ((uintptr_t)final_offset & 0x3ff) final_offset++;
  247. multiboot_header.mods_addr = (uintptr_t)final_offset;
  248. memcpy(final_offset, &modules_mboot, sizeof(modules_mboot));
  249. final_offset += sizeof(modules_mboot);
  250. while ((uintptr_t)final_offset & 0x3ff) final_offset++;
  251. memcpy(final_offset, &multiboot_header, sizeof(multiboot_header));
  252. _ebx = (uintptr_t)final_offset;
  253. print("Jumping to main, good luck.\n");
  254. #else
  255. print_hex(mmap_ent);
  256. print("\n");
  257. memset((void*)KERNEL_LOAD_START, 0x00, 1024);
  258. mboot_memmap_t * mmap = (void*)KERNEL_LOAD_START;
  259. multiboot_header.mmap_addr = (uintptr_t)mmap;
  260. multiboot_header.mods_addr = (uintptr_t)&modules_mboot;
  261. multiboot_header.boot_loader_name = (uintptr_t)VERSION_TEXT;
  262. struct mmap_entry * e820 = (void*)0x5000;
  263. uint64_t upper_mem = 0;
  264. for (int i = 0; i < mmap_ent; ++i) {
  265. print("entry "); print_hex(i); print("\n");
  266. print("base: "); print_hex((uint32_t)e820[i].base); print("\n");
  267. print("type: "); print_hex(e820[i].type); print("\n");
  268. mmap->size = sizeof(uint64_t) * 2 + sizeof(uintptr_t);
  269. mmap->base_addr = e820[i].base;
  270. mmap->length = e820[i].len;
  271. mmap->type = e820[i].type;
  272. if (mmap->type == 1 && mmap->base_addr >= 0x100000) {
  273. upper_mem += mmap->length;
  274. }
  275. mmap = (mboot_memmap_t *) ((uintptr_t)mmap + mmap->size + sizeof(uintptr_t));
  276. }
  277. print("lower "); print_hex(lower_mem); print("KB\n");
  278. multiboot_header.mem_lower = 1024;
  279. print("upper ");
  280. print_hex(upper_mem >> 32);
  281. print_hex(upper_mem);
  282. print("\n");
  283. multiboot_header.mem_upper = upper_mem / 1024;
  284. _ebx = (unsigned int)&multiboot_header;
  285. #endif
  286. _eax = MULTIBOOT_EAX_MAGIC;
  287. _xmain = entry;
  288. #ifdef EFI_PLATFORM
  289. print_("\nExiting boot services and jumping to ");
  290. print_hex_(_xmain);
  291. print_(" with mboot_mag=");
  292. print_hex_(_eax);
  293. print_(" and mboot_ptr=");
  294. print_hex_(_ebx);
  295. print_("...\n");
  296. #if defined(__x86_64__)
  297. print_("&_xmain = "); print_hex_(((uintptr_t)&_xmain) >> 32); print_hex_((uint32_t)(uintptr_t)&_xmain); print_("\n");
  298. #endif
  299. if (1) {
  300. EFI_STATUS e;
  301. UINTN mapSize = 0, mapKey, descriptorSize;
  302. UINT32 descriptorVersion;
  303. uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, NULL, &mapKey, &descriptorSize, NULL);
  304. e = uefi_call_wrapper(ST->BootServices->ExitBootServices, 2, ImageHandleIn, mapKey);
  305. if (e != EFI_SUCCESS) {
  306. print_("Exit services failed. \n");
  307. print_hex_(e);
  308. }
  309. }
  310. #endif
  311. #if defined(__x86_64__)
  312. uint64_t foobar = ((uint32_t)(uintptr_t)&do_the_nasty) | (0x10L << 32L);
  313. uint32_t * foo = (uint32_t *)0x7c00;
  314. foo[0] = _eax;
  315. foo[1] = _ebx;
  316. foo[2] = _xmain;
  317. __asm__ __volatile__ (
  318. "push %0\n"
  319. "retf\n"
  320. : : "g"(foobar));
  321. #else
  322. __asm__ __volatile__ (
  323. "mov %1,%%eax \n"
  324. "mov %2,%%ebx \n"
  325. "jmp *%0" : : "g"(_xmain), "g"(_eax), "g"(_ebx) : "eax", "ebx"
  326. );
  327. #endif
  328. }
  329. #if defined(__x86_64__)
  330. __asm__ (
  331. "do_the_nasty:\n"
  332. "cli\n"
  333. //"mov 0x08, %ax\n"
  334. //"mov %ax, %ds\n"
  335. //"mov %ax, %es\n"
  336. //"mov %ax, %fs\n"
  337. //"mov %ax, %gs\n"
  338. //"mov %ax, %ss\n"
  339. ".code32\n"
  340. "mov %cr0, %eax\n"
  341. "and $0x7FFeFFFF, %eax\n"
  342. "mov %eax, %cr0\n"
  343. // Paging is disabled
  344. "mov $0xc0000080, %ecx\n"
  345. "rdmsr\n"
  346. "and $0xfffffeff, %eax\n"
  347. "wrmsr\n"
  348. "mov $0x640, %eax\n"
  349. "mov %eax, %cr4\n"
  350. "mov 0x7c00, %eax\n"
  351. "mov 0x7c04, %ebx\n"
  352. "mov 0x7c08, %ecx\n"
  353. "jmp *%ecx\n"
  354. "target: jmp target\n"
  355. ".code64\n"
  356. );
  357. #endif
  358. #ifndef EFI_PLATFORM
  359. static void do_it(struct ata_device * _device) {
  360. device = _device;
  361. if (device->atapi_sector_size != 2048) {
  362. print_hex(device->atapi_sector_size);
  363. print("\n - bad sector size\n");
  364. return;
  365. }
  366. for (int i = 0x10; i < 0x15; ++i) {
  367. ata_device_read_sector_atapi(device, i, (uint8_t *)root);
  368. switch (root->type) {
  369. case 1:
  370. root_sector = i;
  371. goto done;
  372. case 0xFF:
  373. return;
  374. }
  375. }
  376. return;
  377. done:
  378. restore_root();
  379. if (navigate(kernel_path)) {
  380. print("Found kernel.\n");
  381. print_hex(dir_entry->extent_start_LSB); print(" ");
  382. print_hex(dir_entry->extent_length_LSB); print("\n");
  383. long offset = 0;
  384. for (int i = dir_entry->extent_start_LSB; i < dir_entry->extent_start_LSB + dir_entry->extent_length_LSB / 2048 + 1; ++i, offset += 2048) {
  385. ata_device_read_sector_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset);
  386. }
  387. while (offset % 4096) offset++;
  388. restore_root();
  389. if (navigate(module_dir)) {
  390. memcpy(mod_dir, dir_entry, sizeof(iso_9660_directory_entry_t));
  391. print("Scanning modules...\n");
  392. char ** c = modules;
  393. int j = 0;
  394. while (*c) {
  395. print("load "); print(*c); print("\n");
  396. if (!navigate(*c)) {
  397. print("Failed to locate module! [");
  398. print(*c);
  399. multiboot_header.mods_count--;
  400. print("]\n");
  401. } else {
  402. modules_mboot[j].mod_start = KERNEL_LOAD_START + offset;
  403. modules_mboot[j].mod_end = KERNEL_LOAD_START + offset + dir_entry->extent_length_LSB;
  404. for (int i = dir_entry->extent_start_LSB; i < dir_entry->extent_start_LSB + dir_entry->extent_length_LSB / 2048 + 1; ++i, offset += 2048) {
  405. ata_device_read_sector_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset);
  406. }
  407. while (offset % 4096) offset++;
  408. j++;
  409. }
  410. c++;
  411. restore_mod();
  412. }
  413. print("Done.\n");
  414. restore_root();
  415. if (navigate(ramdisk_path)) {
  416. //clear_();
  417. ramdisk_off = KERNEL_LOAD_START + offset;
  418. ramdisk_len = dir_entry->extent_length_LSB;
  419. modules_mboot[multiboot_header.mods_count-1].mod_start = ramdisk_off;
  420. modules_mboot[multiboot_header.mods_count-1].mod_end = ramdisk_off + ramdisk_len;
  421. print_("Loading ramdisk");
  422. int i = dir_entry->extent_start_LSB;
  423. int sectors = dir_entry->extent_length_LSB / 2048 + 1;
  424. #define SECTORS 512
  425. while (sectors >= SECTORS) {
  426. print_(".");
  427. ata_device_read_sectors_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset, SECTORS);
  428. sectors -= SECTORS;
  429. offset += 2048 * SECTORS;
  430. i += SECTORS;
  431. }
  432. if (sectors > 0) {
  433. print_("!");
  434. ata_device_read_sectors_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset, sectors);
  435. offset += 2048 * sectors;
  436. }
  437. final_offset = (uint8_t *)KERNEL_LOAD_START + offset;
  438. set_attr(0x07);
  439. print("Done.\n");
  440. move_kernel();
  441. }
  442. } else {
  443. print("No mod directory?\n");
  444. }
  445. } else {
  446. print("boo\n");
  447. }
  448. return;
  449. }
  450. #endif
  451. struct fw_cfg_file {
  452. uint32_t size;
  453. uint16_t select;
  454. uint16_t reserved;
  455. char name[56];
  456. };
  457. static int boot_mode = 0;
  458. void swap_bytes(void * in, int count) {
  459. char * bytes = in;
  460. if (count == 4) {
  461. uint32_t * t = in;
  462. *t = (bytes[0] << 24) | (bytes[1] << 12) | (bytes[2] << 8) | bytes[3];
  463. } else if (count == 2) {
  464. uint16_t * t = in;
  465. *t = (bytes[0] << 8) | bytes[1];
  466. }
  467. }
  468. void show_menu(void) {
  469. #if 1
  470. /* Try to detect qemu headless boot */
  471. outports(0x510, 0x0000);
  472. if (inportb(0x511) == 'Q' &&
  473. inportb(0x511) == 'E' &&
  474. inportb(0x511) == 'M' &&
  475. inportb(0x511) == 'U') {
  476. uint32_t count = 0;
  477. uint8_t * bytes = (uint8_t *)&count;
  478. outports(0x510,0x0019);
  479. for (int i = 0; i < 4; ++i) {
  480. bytes[i] = inportb(0x511);
  481. }
  482. swap_bytes(&count, 4);
  483. #if 0
  484. print_("there are ");
  485. print_hex_(count);
  486. print_(" entries\n");
  487. #endif
  488. unsigned int bootmode_size = 0;
  489. int bootmode_index = -1;
  490. for (unsigned int i = 0; i < count; ++i) {
  491. struct fw_cfg_file file;
  492. uint8_t * tmp = (uint8_t *)&file;
  493. for (int j = 0; j < sizeof(struct fw_cfg_file); ++j) {
  494. tmp[j] = inportb(0x511);
  495. }
  496. if (!strcmp(file.name,"opt/org.toaruos.bootmode")) {
  497. swap_bytes(&file.size, 4);
  498. swap_bytes(&file.select, 2);
  499. bootmode_size = file.size;
  500. bootmode_index = file.select;
  501. }
  502. #if 0
  503. print_("selector "); print_hex_(file.select); print_(" is "); print_hex_(file.size); print_(" bytes\n");
  504. print_("and its name is: "); print_(file.name); print_("\n");
  505. #endif
  506. }
  507. if (bootmode_index != -1) {
  508. outports(0x510, bootmode_index);
  509. char tmp[33] = {0};
  510. for (int i = 0; i < 32 && i < bootmode_size; ++i) {
  511. tmp[i] = inportb(0x511);
  512. }
  513. for (int i = 0; i < BASE_SEL+1; ++i) {
  514. if (!strcmp(tmp,boot_mode_names[i].key)) {
  515. boot_mode = boot_mode_names[i].index;
  516. return;
  517. }
  518. }
  519. print_("fw_cfg boot mode not recognized: ");
  520. print_(tmp);
  521. print_("\n");
  522. }
  523. }
  524. #endif
  525. /* Determine number of options */
  526. sel_max = 0;
  527. while (boot_options[sel_max].value) {
  528. sel_max++;
  529. }
  530. sel_max += BASE_SEL + 1;
  531. #ifndef EFI_PLATFORM
  532. outportb(0x3D4, 14);
  533. outportb(0x3D5, 0xFF);
  534. outportb(0x3D4, 15);
  535. outportb(0x3D5, 0xFF);
  536. inportb(0x3DA);
  537. outportb(0x3C0, 0x30);
  538. char b = inportb(0x3C1);
  539. b &= ~8;
  540. outportb(0x3c0, b);
  541. #endif
  542. clear_();
  543. do {
  544. move_cursor(0,0);
  545. set_attr(0x1f);
  546. print_banner(VERSION_TEXT);
  547. set_attr(0x07);
  548. print_("\n");
  549. for (int i = 0; i < BASE_SEL+1; ++i) {
  550. set_attr(sel == i ? 0x70 : 0x07);
  551. print_(" ");
  552. char tmp[] = {'0' + (i + 1), '.', ' ', '\0'};
  553. print_(tmp);
  554. print_(boot_mode_names[i].title);
  555. print_("\n");
  556. }
  557. // put a gap
  558. set_attr(0x07);
  559. print_("\n");
  560. for (int i = 0; i < sel_max - BASE_SEL - 1; ++i) {
  561. toggle(BASE_SEL + 1 + i, *boot_options[i].value, boot_options[i].title);
  562. }
  563. set_attr(0x07);
  564. move_cursor(x,17);
  565. print_("\n");
  566. print_banner(HELP_TEXT);
  567. print_("\n");
  568. if (sel > BASE_SEL) {
  569. print_banner(boot_options[sel-BASE_SEL-1].description_1);
  570. print_banner(boot_options[sel-BASE_SEL-1].description_2);
  571. print_("\n");
  572. } else {
  573. print_banner(COPYRIGHT_TEXT);
  574. print_("\n");
  575. print_banner(LINK_TEXT);
  576. }
  577. int s = read_scancode();
  578. if (s == 0x50) { /* DOWN */
  579. if (sel > BASE_SEL && sel < sel_max - 1) {
  580. sel = (sel + 2) % sel_max;
  581. } else {
  582. sel = (sel + 1) % sel_max;
  583. }
  584. } else if (s == 0x48) { /* UP */
  585. if (sel > BASE_SEL + 1) {
  586. sel = (sel_max + sel - 2) % sel_max;
  587. } else {
  588. sel = (sel_max + sel - 1) % sel_max;
  589. }
  590. } else if (s == 0x4B) { /* LEFT */
  591. if (sel > BASE_SEL) {
  592. if ((sel - BASE_SEL) % 2) {
  593. sel = (sel + 1) % sel_max;
  594. } else {
  595. sel -= 1;
  596. }
  597. }
  598. } else if (s == 0x4D) { /* RIGHT */
  599. if (sel > BASE_SEL) {
  600. if ((sel - BASE_SEL) % 2) {
  601. sel = (sel + 1) % sel_max;
  602. } else {
  603. sel -= 1;
  604. }
  605. }
  606. } else if (s == 0x1c) {
  607. if (sel <= BASE_SEL) {
  608. boot_mode = boot_mode_names[sel].index;
  609. break;
  610. } else {
  611. int index = sel - BASE_SEL - 1;
  612. *boot_options[index].value = !*boot_options[index].value;
  613. }
  614. } else if (s >= 2 && s <= 10) {
  615. int i = s - 2;
  616. if (i <= BASE_SEL) {
  617. boot_mode = boot_mode_names[i].index;
  618. break;
  619. }
  620. #if 0
  621. } else {
  622. print_hex_(s);
  623. #endif
  624. }
  625. } while (1);
  626. }
  627. #ifdef EFI_PLATFORM
  628. /* EFI boot uses simple filesystem driver */
  629. static EFI_GUID efi_simple_file_system_protocol_guid =
  630. {0x0964e5b22,0x6459,0x11d2,0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b};
  631. static EFI_GUID efi_loaded_image_protocol_guid =
  632. {0x5B1B31A1,0x9562,0x11d2, {0x8E,0x3F,0x00,0xA0,0xC9,0x69,0x72,0x3B}};
  633. static void boot(void) {
  634. UINTN count;
  635. EFI_HANDLE * handles;
  636. EFI_LOADED_IMAGE * loaded_image;
  637. EFI_FILE_IO_INTERFACE *efi_simple_filesystem;
  638. EFI_FILE *root;
  639. EFI_STATUS status;
  640. clear_();
  641. status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
  642. 3, ImageHandleIn, &efi_loaded_image_protocol_guid,
  643. (void **)&loaded_image);
  644. if (EFI_ERROR(status)) {
  645. print_("There was an error (init)\n");
  646. while (1) {};
  647. }
  648. print_("Found loaded image...\n");
  649. status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
  650. 3, loaded_image->DeviceHandle, &efi_simple_file_system_protocol_guid,
  651. (void **)&efi_simple_filesystem);
  652. if (EFI_ERROR(status)) {
  653. print_("There was an error.\n");
  654. while (1) {};
  655. }
  656. status = uefi_call_wrapper(efi_simple_filesystem->OpenVolume,
  657. 2, efi_simple_filesystem, &root);
  658. if (EFI_ERROR(status)) {
  659. print_("There was an error.\n");
  660. while (1) {};
  661. }
  662. EFI_FILE * file;
  663. CHAR16 kernel_name[16] = {0};
  664. {
  665. char * c = kernel_path;
  666. char * ascii = c;
  667. int i = 0;
  668. while (*ascii) {
  669. kernel_name[i] = *ascii;
  670. i++;
  671. ascii++;
  672. }
  673. if (kernel_name[i-1] == L'.') {
  674. kernel_name[i-1] = 0;
  675. }
  676. }
  677. /* Load kernel */
  678. status = uefi_call_wrapper(root->Open,
  679. 5, root, &file, kernel_name, EFI_FILE_MODE_READ, 0);
  680. if (EFI_ERROR(status)) {
  681. print_("There was an error.\n");
  682. while (1) {};
  683. }
  684. unsigned int offset = 0;
  685. UINTN bytes = 134217728;
  686. status = uefi_call_wrapper(file->Read,
  687. 3, file, &bytes, (void *)KERNEL_LOAD_START);
  688. if (EFI_ERROR(status)) {
  689. print_("There was an error.\n");
  690. while (1) {};
  691. }
  692. print_("Read "); print_hex_(bytes); print_(" bytes\n");
  693. offset += bytes;
  694. while (offset % 4096) offset++;
  695. print_("Reading modules...\n");
  696. char ** c = modules;
  697. int j = 0;
  698. while (*c) {
  699. if (strcmp(*c, "NONE")) {
  700. /* Try to load module */
  701. CHAR16 name[16] = {0};
  702. name[0] = L'm';
  703. name[1] = L'o';
  704. name[2] = L'd';
  705. name[3] = L'\\';
  706. char * ascii = *c;
  707. int i = 0;
  708. while (*ascii) {
  709. name[i+4] = (*ascii >= 'A' && *ascii <= 'Z') ? (*ascii - 'A' + 'a') : *ascii;
  710. name[i+5] = 0;
  711. i++;
  712. ascii++;
  713. }
  714. for (int i = 0; name[i]; ++i) {
  715. char c[] = {name[i], 0};
  716. print_(c);
  717. }
  718. print_("\n");
  719. bytes = 2097152;
  720. _try_module_again:
  721. status = uefi_call_wrapper(root->Open,
  722. 5, root, &file, name, EFI_FILE_MODE_READ, 0);
  723. if (!EFI_ERROR(status)) {
  724. status = uefi_call_wrapper(file->Read,
  725. 3, file, &bytes, (void *)(KERNEL_LOAD_START + (uintptr_t)offset));
  726. if (!EFI_ERROR(status)) {
  727. print_("Loaded "); print_(*c); print_("\n");
  728. modules_mboot[j].mod_start = KERNEL_LOAD_START + offset;
  729. modules_mboot[j].mod_end = KERNEL_LOAD_START + offset + bytes;
  730. j++;
  731. offset += bytes;
  732. while (offset % 4096) offset++;
  733. }
  734. } else {
  735. print_("Error opening "); print_(*c); print_(" "); print_hex_(status); print_("\n");
  736. while (1) { };
  737. }
  738. } else {
  739. multiboot_header.mods_count--;
  740. }
  741. c++;
  742. }
  743. {
  744. char * c = ramdisk_path;
  745. CHAR16 name[16] = {0};
  746. char * ascii = c;
  747. int i = 0;
  748. while (*ascii) {
  749. name[i] = *ascii;
  750. i++;
  751. ascii++;
  752. }
  753. if (name[i-1] == L'.') {
  754. name[i-1] == 0;
  755. }
  756. bytes = 134217728;
  757. status = uefi_call_wrapper(root->Open,
  758. 5, root, &file, name, EFI_FILE_MODE_READ, 0);
  759. if (!EFI_ERROR(status)) {
  760. status = uefi_call_wrapper(file->Read,
  761. 3, file, &bytes, (void *)(KERNEL_LOAD_START + (uintptr_t)offset));
  762. if (!EFI_ERROR(status)) {
  763. print_("Loaded "); print_(c); print_("\n");
  764. modules_mboot[multiboot_header.mods_count-1].mod_start = KERNEL_LOAD_START + offset;
  765. modules_mboot[multiboot_header.mods_count-1].mod_end = KERNEL_LOAD_START + offset + bytes;
  766. offset += bytes;
  767. while (offset % 4096) offset++;
  768. final_offset = (uint8_t *)KERNEL_LOAD_START + offset;
  769. } else {
  770. print_("Failed to read ramdisk\n");
  771. }
  772. } else {
  773. print_("Error opening "); print_(c); print_("\n");
  774. }
  775. }
  776. move_kernel();
  777. }
  778. #else
  779. /* BIOS boot uses native ATAPI drivers, need to find boot drive. */
  780. static void boot(void) {
  781. clear_();
  782. multiboot_header.cmdline = (uintptr_t)cmdline;
  783. ata_device_detect(&ata_primary_master);
  784. ata_device_detect(&ata_primary_slave);
  785. ata_device_detect(&ata_secondary_master);
  786. ata_device_detect(&ata_secondary_slave);
  787. if (ata_primary_master.is_atapi) {
  788. do_it(&ata_primary_master);
  789. }
  790. if (ata_primary_slave.is_atapi) {
  791. do_it(&ata_primary_slave);
  792. }
  793. if (ata_secondary_master.is_atapi) {
  794. do_it(&ata_secondary_master);
  795. }
  796. if (ata_secondary_slave.is_atapi) {
  797. do_it(&ata_secondary_slave);
  798. }
  799. while (1);
  800. }
  801. #endif