U0 BlkDevLockFwdingSet(CBlkDev *bd) { //If two blkdevs on same controller, use just one lock CBlkDev *bd1; I64 i; switch (bd->type) { case BDT_RAM: break; case BDT_ISO_FILE_READ: case BDT_ISO_FILE_WRITE: bd->lock_fwding = Letter2BlkDev(*bd->file_disk_name); break; case BDT_ATA: case BDT_ATAPI: for (i = 0; i < BLKDEVS_NUM; i++) { bd1 = &blkdev.blkdevs[i]; if (bd1->bd_signature == BD_SIGNATURE_VAL && bd != bd1 && (bd1->type == BDT_ATAPI || bd1->type == BDT_ATA) && bd1->port_num == bd->port_num) { bd->lock_fwding = bd1; break; } } break; } } I64 BlkDevAdd(CBlkDev *bd, I64 prt_num=I64_MIN, Bool whole_drive, Bool make_free) {//It will mount just one partition of prt_num>=0. //When repartitioing whole drive, whole_drive=TRUE. I64 i, j, ext_base, offset, res = 0, num = 0; CDrive *drive; CRedSeaBoot br; CMasterBoot mbr; bd->bd_signature = BD_SIGNATURE_VAL; if (make_free) drive = DriveMakeFreeSlot(bd->first_drive_let); else drive = DriveMakeFreeSlot(DriveNextFreeLet(bd->first_drive_let)); drive->bd = bd; drive->drv_offset = bd->drv_offset; drive->size = bd->max_blk + 1 - bd->drv_offset; switch (bd->type) { case BDT_RAM: case BDT_ISO_FILE_READ: case BDT_ISO_FILE_WRITE: drive->drive_signature = DRIVE_SIGNATURE_VAL; drive->prt_num = num; drive->fs_type = FSt_REDSEA; //This is to force creation of a RAM //drive during boot, so it is probably //MAlloced to the same address and can //be assumed to be already formatted. //If this line is removed, RAM Drives //will be alloced on a just-in-time //basis. if (BlkDevInit(bd)) res++; else drive->drive_signature = 0; break; case BDT_ATA: drive->drive_signature = DRIVE_SIGNATURE_VAL; //Temporarily validate if (!BlkDevInit(bd)) drive->drive_signature = 0; //Revoke validation else { drive->drive_signature = 0; //Revoke validation if (whole_drive) { drive->drive_signature = DRIVE_SIGNATURE_VAL; drive->prt_num = num; res++; drive->fs_type = FSt_REDSEA; drive->size = bd->max_blk + 1 - bd->drv_offset; //The following read is a test read. //if it hangs, the drive is not supported. AHCIAtaBlksRead(bd, &mbr, 0, 1); break; } offset = 0; ext_base = INVALID_CLUS; while (prt_num < 0 || num <= prt_num) { AHCIAtaBlksRead(bd, &mbr, offset, 1); if (mbr.signature != 0xAA55) break; j = -1; for (i = 0; i < 4 && (prt_num < 0 || num <= prt_num); i++) { if (mbr.p[i].type) { if (make_free) drive = DriveMakeFreeSlot(bd->first_drive_let + res); else drive = DriveMakeFreeSlot(DriveNextFreeLet(bd->first_drive_let + res)); drive->bd = bd; drive->drv_offset = mbr.p[i].offset + offset; drive->size = mbr.p[i].size; switch (mbr.p[i].type) { case MBR_PT_REDSEA: drive->drive_signature = DRIVE_SIGNATURE_VAL; drive->prt_num = num; res++; drive->fs_type = FSt_REDSEA; RedSeaInit(drive); break; case MBR_PT_FAT32a: case MBR_PT_FAT32b: case MBR_PT_FAT32c: case MBR_PT_FAT32d: case MBR_PT_FAT32e: case MBR_PT_FAT32f: AHCIAtaBlksRead(bd, &br, drive->drv_offset, 1); drive->drive_signature = DRIVE_SIGNATURE_VAL; drive->prt_num = num; res++; if (br.signature == MBR_PT_REDSEA) { drive->fs_type = FSt_REDSEA; RedSeaInit(drive); } else { drive->fs_type = FSt_FAT32; FAT32Init(drive); } break; case MBR_PT_NTFS: drive->drive_signature = DRIVE_SIGNATURE_VAL; drive->prt_num = num; res++; drive->fs_type = FSt_NTFS; break; case MBR_PT_LINUX: drive->drive_signature = DRIVE_SIGNATURE_VAL; drive->prt_num = num; res++; drive->fs_type = FSt_LINUX; break; case MBR_PT_SWAP: drive->drive_signature = DRIVE_SIGNATURE_VAL; drive->prt_num = num; res++; drive->fs_type = FSt_SWAP; break; case 5: case 15: j = i; break; default: drive->drive_signature = DRIVE_SIGNATURE_VAL; drive->prt_num = num; res++; drive->fs_type = FSt_UNKNOWN; } num++; } } if (Letter2BlkDevType(bd->first_drive_let + res) != bd->type) break; if (j < 0) break; if (!mbr.p[j].offset) break; if (ext_base == INVALID_CLUS) { offset = mbr.p[j].offset; ext_base = offset; } else offset = mbr.p[j].offset + ext_base; } } break; case BDT_ATAPI: drive->drive_signature = DRIVE_SIGNATURE_VAL; drive->prt_num = num; res++; drive->fs_type = FSt_ISO9660; //Start with this drive->size = 0; break; } if (res) BlkDevLockFwdingSet(bd); else BlkDevDel(bd); return res; } Bool DriveEnable(U8 drv_let, Bool val) {//Can unmount or remount, but not mount the first time. CDrive *drive; if (drive = Letter2Drive(drv_let, FALSE)) return !LBEqual(&drive->fs_type, FStf_DISABLE, !val); else return FALSE; } I64 SysI64Get() { U8 st[STR_LEN]; StrNGet(st, STR_LEN, FALSE); return Str2I64(st, 16); } U0 BlkDevsInitAll() { CBlkDev *bd; I64 i; blkdev.blkdevs = CAlloc(sizeof(CBlkDev) * BLKDEVS_NUM); blkdev.drvs = CAlloc(sizeof(CDrive) * DRIVES_NUM); for (i = 0; i < DRIVES_NUM; i++) blkdev.let_to_drive[i] = &blkdev.drvs[i]; "\nAHCIInit;\n"; AHCIInit; if (!blkdev.ahci_hba) { "\nZealOS requires AHCI.\n\n" "If in IDE compatibility mode, switch to SATA mode.\n" "If running in a VM, ensure disks are organized under a SATA controller.\n\n" "Rebooting in 10 seconds...\n"; Sleep(10*1000); Reboot; } #exe { if (kernel_config->opts[CONFIG_MOUNT_AHCI_AUTO]) StreamPrint("MountAHCIAuto;"); StreamPrint("#exe {Option(OPTf_WARN_PAREN, OFF);}"); StreamDoc(kernel_config->add_dev); StreamPrint("#exe {Option(OPTf_WARN_PAREN, ON);}"); }; }