#define LIMINE_HDD_FILE "/Boot/Limine-BIOS-HDD.HH" #define LIMINE_HDD_INSTALLER "/System/Boot/LimineMHDIns.ZC" #include LIMINE_HDD_FILE #include LIMINE_HDD_INSTALLER #define LIMINE_INSTALL_PROMPT \ "Install $GREEN$Public Domain$FG$ ZealOS Boot Loader,\n" \ "or $RED$BSD-2 licensed$FG$ Limine Boot Loader?\n\n" \ "$DKGRAY$ZealOS Boot Loader is written in public-domain ZealC, but only supports BIOS mode.\n\n" \ "Limine supports UEFI and BIOS mode and multiple boot protocols, but is written in BSD-2 licensed C code, and cannot be modified within ZealOS.$FG$\n\n\n" // TODO FIXME: refactor OSUpgrade code into optional Diff prompt to compare ISO<->HDD before Install. CDirEntry OSFilesMGFind(CDirEntry *needle_entry, CDirEntry *haystack_list) { while (haystack_list) { if (!StrCompare(needle_entry->name, haystack_list->name)) return haystack_list; haystack_list = haystack_list->next; } return NULL; } U0 OSFilesMergeInner(CDirEntry *tmpde1, CDirEntry *tmpde2, I64 *_df_flags) { CDirEntry *tmpde; U8 *new; while (tmpde1 && !(*_df_flags & DF_ABORT_ALL_FILES)) { tmpde = OSFilesMGFind(tmpde1, tmpde2); if (!tmpde) { "$BROWN$Does Not Exist:%s$FG$\n", tmpde1->full_name; new = StrNew(tmpde1->full_name); new[0] = tmpde2->full_name[0]; // shortcut to quickly get drive letter if (tmpde1->attr & RS_ATTR_DIR) CopyTree(tmpde1->full_name, new); else { Copy(tmpde1->full_name, new); } Free(new); } else { if (tmpde1->attr & RS_ATTR_DIR) OSFilesMergeInner(tmpde1->sub, tmpde->sub, _df_flags); else { if (FilesFindMatch(tmpde1->full_name, FILEMASK_TXT)) { "\n$LTRED$%s$FG$\n", tmpde->full_name; "$LTGREEN$%s$FG$\n", tmpde1->full_name; Diff(tmpde->full_name, tmpde1->full_name, _df_flags); } } } tmpde1 = tmpde1->next; } } U0 OSFilesMerge(U8 *dst_files_find_mask="/*", U8 *src_files_find_mask="/*", U8 *fu_flags=NULL) { // See Merge. I64 df_flags, fuf_flags = 0, ch; CDirEntry *tmpde1 = NULL, *tmpde2 = NULL; FlagsScan(&fuf_flags, Define("ST_FILE_UTIL_FLAGS"), "+r"); FlagsScan(&fuf_flags, Define("ST_FILE_UTIL_FLAGS"), fu_flags); if (fuf_flags & ~(FUG_FILES_FIND | FUF_DIFF)) throw('FUF'); PrintWarn("This is based strictly on file dates.\n"); tmpde1 = FilesFind(src_files_find_mask, fuf_flags & FUG_FILES_FIND); tmpde2 = FilesFind(dst_files_find_mask, fuf_flags & FUG_FILES_FIND); "\n\nManual or Automatic Upgrade? (M/A): "; do ch = ToUpper(CharGet(, FALSE)); while (ch != 'M' && ch != 'A'); "%c\n", ch; if (ch == 'M') { PopUpOk("\n$LTGREEN$FILE2$FG$ is new changes.\n" "$LTRED$FILE1$FG$ is from existing install."); df_flags = 0; OSFilesMergeInner(tmpde1, tmpde2, &df_flags); } else { df_flags = DF_REMAINDER_ALL_FILE2 | DF_NO_MORE_PROMPTS_THIS_FILE | DF_KEEP_FLAGS; OSFilesMergeInner(tmpde1, tmpde2, &df_flags); } DirTreeDel(tmpde1); DirTreeDel(tmpde2); } U0 OSMerge(U8 dst_drv, U8 src_drv=':') { U8 *dst = MStrPrint("%C:/", dst_drv); U8 *src = MStrPrint("%C:/", src_drv); CopyTree(dst, "B:/"); Del("B:/Misc/Bible.TXT"); // Deleting from B:/ prevents causing hang when merging large .TXT files, Del("B:/Misc/Clementine.TXT"); // they will instead be copied over from boot drive in OSMergeInner Del("B:/Boot/Limine.CFG"); // Delete to make merge output ignore (copy) this, since it gets regenerated later DocMax; "$PB$$PB$$LTCYAN$Beginning Upgrade (running OSFilesMerge) ...$FG$\n\n"; OSFilesMerge("B:/", src, "+d"); "\n\n$LTCYAN$Upgrade merge completed." "\nChanges listed above, scroll up to see all." "\n\nPress ESC when you are ready to finish Upgrade (write merged files to disk).$FG$\n\n"; View; DocBottom; CopyTree("B:/", dst); ExePrint("Del(\"%C:/Boot/Limine-BIOS-CD.BIN\");", dst_drv); ExePrint("Del(\"%C:/Boot/Limine-UEFI-CD.BIN\");", dst_drv); ExePrint("Del(\"%C:/Boot/Limine.CFG\");", dst_drv); ExePrint("Del(\"%C:/boot.catalog\");", dst_drv); } U0 OSUpgrade() { I64 drv_let, ch; U8 *st, *port_st; CTask *task; task = User; TaskWait(task); task->border_src = BDS_CONST; task->border_attr = LTGRAY << 4 + DriveTextAttrGet(':') & 15; task->text_attr = LTGRAY << 4 + BLUE; task->win_inhibit = WIG_TASK_DEFAULT - WIF_SELF_BORDER; WinHorz(Fs->win_left, Fs->win_right, task); WinVert(Fs->win_top, (Fs->win_top + Fs->win_bottom) >> 2 - 1, task); WinVert(task->win_bottom + 3, Fs->win_bottom); WinToTop(Fs); XTalk(task, "Mount;\nC\n"); "\n\nSelect the port of the ATA drive with an existing installation.\n\n"; "Hard Drive Port: "; while (TRUE) { port_st = StrGet; if ((0 <= Str2I64(port_st) < AHCI_MAX_PORTS) && ((&blkdev.ahci_hba->ports[Str2I64(port_st)])->signature == AHCI_PxSIG_ATA)) { break; } Free(port_st); } XTalkWait(task, "%s\n\n", port_st); DriveRep; do { st = StrGet("\nInstallation Partition Letter: "); if (*st) drv_let = Letter2Letter(*st); else drv_let = 0; Free(st); } while (!('A' <= drv_let <= 'Z')); '\n'; OSMerge(drv_let); // src_drv needed? XTalkWait(task, "BootHDIns('%C');\n\nB\n0x20000\nC\n%s\n\n", drv_let, port_st); XTalkWait(task, "\n\n"); //skip through Disk Cache, Options if (!sys_is_uefi_booted) { "$RED$Install Master Boot Loader?$FG$"; if (YorN) { "\n\n"; if (FileFind(LIMINE_HDD_FILE)) { "" LIMINE_INSTALL_PROMPT; "(Z/L): "; do ch = ToUpper(CharGet(, FALSE)); while (ch != 'Z' && ch != 'L'); "%c\n", ch; if (ch == 'Z') { BootMHDIns(drv_let); "\n(Generating optional UEFI-mode Limine.CFG...)\n"; LimineCFGMake(drv_let); } else { LimineMHDIns(drv_let); } "\n\n"; } else BootMHDIns(drv_let); } } else LimineCFGMake(drv_let); WinVert(task->win_top, Fs->win_bottom); Kill(task); } U0 InstallDrive(U8 drv_let) { U8 *st; while (!DriveCheck(blkdev.let_to_drive[drv_let - 'A'], FALSE)) Sleep(1); Sleep(1000); '.'; Sleep(1000); '.'; Sleep(1000); '.'; Sleep(1000); ExePrint("CopyTree(\"::/\",\"%C:/\");", drv_let); ExePrint("Del(\"%C:/Boot/Limine-BIOS-CD.BIN\");", drv_let); ExePrint("Del(\"%C:/Boot/Limine-UEFI-CD.BIN\");", drv_let); ExePrint("Del(\"%C:/Boot/Limine.CFG\");", drv_let); ExePrint("Del(\"%C:/boot.catalog\");", drv_let); ExePrint("DirMake(\"%C:/Tmp\");", drv_let); ExePrint("DirMake(\"%C:/Tmp/ScreenShots\");", drv_let); ExePrint("DirMake(\"%C:/Home\");", drv_let); st = MStrPrint("%C:/Home/DoDistro.ZC", drv_let); if (!FileFind(st)) Copy("::/Misc/DoDistro.ZC", st); Free(st); st = MStrPrint("%C:/Home/MakeHome.ZC", drv_let); if (!FileFind(st)) Copy("::/MakeHome.ZC", st); Free(st); } Bool VMPartDisk(CTask *task, I64 ata_port) { if (ata_port > -1) { XTalkWait(task, "DiskPart(,0.5,0.5);\nC\n%d\nY", ata_port); // DOUBLE CHECK INFILE return TRUE; } else return FALSE; } U0 VMInstallDrive(CTask *task, U8 drv_let, I64 ata_port, I64 atapi_port) {// DOUBLE CHECK INFILE InstallDrive(drv_let); XTalkWait(task, "BootHDIns('%C');\n\nB\n0x20000\n", drv_let); if (ata_port > -1) XTalkWait(task, "C\n%d\n", ata_port); if (atapi_port > -1) XTalkWait(task, "T%d\n", atapi_port); XTalkWait(task, "\n\n\n\n"); //Exit Drives, skip Disk Cache and Options } U0 VMInstallWiz() { CTask *task; I64 i, atapi_port = -1, ata_port = -1, ch; CAHCIPort *port; task = User; TaskWait(task); task->border_src = BDS_CONST; task->border_attr = LTGRAY << 4 + DriveTextAttrGet(':') & 15; task->text_attr = LTGRAY << 4 + BLUE; task->win_inhibit = WIG_TASK_DEFAULT - WIF_SELF_BORDER; WinHorz(Fs->win_left, Fs->win_right, task); WinVert(Fs->win_top, (Fs->win_top + Fs->win_bottom) >> 2 - 1, task); WinVert(task->win_bottom + 3, Fs->win_bottom); WinToTop(Fs); SATARep; for (i = 0; i < AHCI_MAX_PORTS; i++) { if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) { port = &blkdev.ahci_hba->ports[i]; if (port->signature == AHCI_PxSIG_ATA) { ata_port = i; break; } } } for (i = 0; i < AHCI_MAX_PORTS; i++) { if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) { port = &blkdev.ahci_hba->ports[i]; if (port->signature == AHCI_PxSIG_ATAPI) { atapi_port = i; break; } } } if (VMPartDisk(task, ata_port)) { VMInstallDrive(task, 'C', ata_port, atapi_port); VMInstallDrive(task, 'D', ata_port, atapi_port); if (!sys_is_uefi_booted) { if (FileFind(LIMINE_HDD_FILE)) { "\n\n" "" LIMINE_INSTALL_PROMPT; "(Z/L): "; do ch = ToUpper(CharGet(, FALSE)); while (ch != 'Z' && ch != 'L'); "%c\n", ch; if (ch == 'Z') { BootMHDIns('C'); "\n(Generating optional UEFI-mode Limine.CFG...)\n"; LimineCFGMake('C'); } else { LimineMHDIns('C'); } "\n\n"; } else BootMHDIns('C'); } else LimineCFGMake('C'); } WinVert(task->win_top, Fs->win_bottom); Kill(task); } U0 RegularInstallWiz() { I64 drv_let; U8 *st, *port_st; I64 ch; CTask *task; task = User; TaskWait(task); task->border_src = BDS_CONST; task->border_attr = LTGRAY << 4 + DriveTextAttrGet(':') & 15; task->text_attr = LTGRAY << 4 + BLUE; task->win_inhibit = WIG_TASK_DEFAULT - WIF_SELF_BORDER; WinHorz(Fs->win_left, Fs->win_right, task); WinVert(Fs->win_top, (Fs->win_top + Fs->win_bottom) >> 2 - 1, task); WinVert(task->win_bottom + 3, Fs->win_bottom); WinToTop(Fs); XTalk(task, "Mount;\nC\n"); "\nSelect the port of the ATA drive to install on.\n"; "Hard Drive Port: "; while (TRUE) { port_st = StrGet; if ((0 <= Str2I64(port_st) < AHCI_MAX_PORTS) && ((&blkdev.ahci_hba->ports[Str2I64(port_st)])->signature == AHCI_PxSIG_ATA)) { break; } Free(port_st); } XTalkWait(task, "%s\n\n", port_st); DriveRep; do { st = StrGet("\nDestination Partition Letter: "); if (*st) drv_let = Letter2Letter(*st); else drv_let = 0; Free(st); } while (!('A' <= drv_let <= 'Z')); '\n'; "$RED$Format %C Partition?$FG$\n", drv_let; if (YorN) { '\n'; do { "$PURPLE$1$FG$) Use FAT32\n" "$PURPLE$2$FG$) Use RedSea\n" "\nFile System Type: "; ch = CharGet; '\n'; } while (!('1' <= ch <= '2')); if (ch == '1') Format(drv_let,, FALSE, FSt_FAT32); else Format(drv_let,, FALSE, FSt_REDSEA); } InstallDrive(drv_let); XTalkWait(task, "BootHDIns('%C');\n\nB\n0x20000\nC\n%s\n\n", drv_let, port_st); XTalkWait(task, "\n\n"); //skip through Disk Cache, Options if (!sys_is_uefi_booted) { "$RED$Install Master Boot loader?$FG$"; if (YorN) { "\n\n"; if (FileFind(LIMINE_HDD_FILE)) { "" LIMINE_INSTALL_PROMPT; "(Z/L): "; do ch = ToUpper(CharGet(, FALSE)); while (ch != 'Z' && ch != 'L'); "%c\n", ch; if (ch == 'Z') { BootMHDIns(drv_let); "\n(Generating optional UEFI-mode Limine.CFG...)\n"; LimineCFGMake(drv_let); // ensures we don't leave the LiveCD's Limine.CFG on the HDD } else { LimineMHDIns(drv_let); } "\n\n"; } else BootMHDIns(drv_let); } } else LimineCFGMake(drv_let); WinVert(task->win_top, Fs->win_bottom); Kill(task); } U0 DoInstructions() { CTask *task = User; AutoComplete; WinToTop(Fs); WinTileVert; XTalk(task, "Ed(\"::/Doc/Install.DD\");\n"); } Bool DoInstall(Bool prompt_reboot) { I64 res = FALSE, vm_install = TRUE, ch; CSMBIOSSystemInfo *sys_info = SMBIOSStructGet(SMBIOSt_SYSTEM); U8 *company = SMBIOSStr(sys_info, sys_info->manufacturer); if (StrCompare(company, "VMware, Inc.") && StrCompare(company, "innotek GmbH") && StrCompare(company, "QEMU")) { "\n\n\n\n\nAre you installing inside VMware, QEMU, VirtualBox or a similar virtual machine? "; vm_install = YorN; } DocBottom; if (vm_install) { "\n\nUpgrade an existing install," "\nor create new Installation? (U/I): "; do ch = ToUpper(CharGet(, FALSE)); while (ch != 'U' && ch != 'I'); "%c\n", ch; if (ch == 'U') OSUpgrade; else VMInstallWiz(); res = TRUE; } else { "\n\nThis wizard works if you have a partition ready. You can partition the drive or BootHDIns() " "with more options if you do it by hand, not using this wizard.\n\n" "Continue Install Wizard "; if (YorN) { "\n\nUpgrade an existing install," "\nor create new Installation? (U/I): "; do ch = ToUpper(CharGet(, FALSE)); while (ch != 'U' && ch != 'I'); "%c\n", ch; if (ch == 'I') { RegularInstallWiz(); res = TRUE; } else { OSUpgrade; res = TRUE; } } else prompt_reboot = FALSE; } if (prompt_reboot) { "Reboot Now "; if (YorN) { DiscEject(':'); Reboot; }; } return res; } Bool OSInstall(Bool prompt_reboot=TRUE) { DoInstructions; return DoInstall(prompt_reboot); } #if __CMD_LINE__ OSInstall(TRUE); #endif