// // Created by rick on 06-02-21. // #include "mbr.h" #include #include #include #include #include #include #include typedef struct { uint8_t bootable; uint8_t starting_head; uint8_t starting_sector: 6; uint16_t starting_cylinder: 10; uint8_t system_id; uint8_t ending_head; uint8_t ending_sector: 6; uint16_t ending_cylinder: 10; uint32_t start_lba; uint32_t num_lbas; } packed mbr_partition_table_entry; typedef struct { uint32_t unique_id; uint16_t reserved; mbr_partition_table_entry entries[4]; uint8_t signature[2]; } packed mbr_table; typedef struct { const block_device *device; uint32_t start_lba; } mbr_block_driver_info; uint8_t mbr_block_dev_access(const block_device *device, uint8_t direction, uint32_t lba, uint8_t sectors, void *target) { if (!device->flags.present || lba > device->num_lba) { return BLOCK_DEV_ACCESS_ERR; } const mbr_block_driver_info *info = device->device_info; const uint32_t actual_lba = info->start_lba + lba; if (actual_lba > info->device->num_lba) { return BLOCK_DEV_ACCESS_ERR; } // delegate to backing driver return info->device->access(info->device, direction, actual_lba, sectors, target); } uint8_t used mbr_check_device(const block_device *device, uint8_t *first_sector) { mbr_table table; memcpy((uint8_t *) &table, first_sector + (device->block_size - sizeof(mbr_table)), sizeof(mbr_table)); if (table.signature[0] != 0x55 && table.signature[1] != 0xAA) { // AA 55 but in little endian return BLOCK_DEV_DRIVER_CHECK_NO_MATCH; } if (table.reserved != 0x0000 && table.reserved != 0x5A5A) { return BLOCK_DEV_DRIVER_CHECK_NO_MATCH; } for (int i = 0; i < 4; ++i) { if (table.entries[i].num_lbas > device->num_lba || table.entries[i].start_lba > device->num_lba) { return BLOCK_DEV_DRIVER_CHECK_NO_MATCH; } } for (int i = 0; i < 4; ++i) { if (table.entries[i].system_id == 0) continue; mbr_block_driver_info *info = malloc(sizeof(mbr_block_driver_info)); info->device = device; info->start_lba = table.entries[i].start_lba; block_device logical_device = { .flags.present = 1, .num_lba = table.entries[i].num_lbas, .block_size = device->block_size, .access = mbr_block_dev_access, .device_info = info, }; sprintf(logical_device.identifier, "%sp%d", device->identifier, i); block_dev_register(&logical_device); } return BLOCK_DEV_DRIVER_CHECK_OK; } void mbr_read_from_ide(uint8_t ide_drive) { char *mbr_data = malloc(0x200); ide_access(0, ide_drive, 0, 1, mbr_data); mbr_partition_table_entry *entry = (mbr_partition_table_entry *) (mbr_data + 0x1BE); printf("Start at %d, count: %d\n", entry->start_lba, entry->num_lbas); free(mbr_data); } BLOCK_DEV_DRIVER(200) = { .name = "mbr", .flags.root_only = 1, .check_device = mbr_check_device, .free_device = NULL, // todo };