From 2cfa67b8e21dbf7eabd0441fdb9c9c4b81b68cb4 Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Thu, 4 Nov 2021 20:14:48 +0100 Subject: [PATCH] Add partition table support --- Makefile | 5 +- README.md | 13 +++++ custom_gdb_extension.py | 4 +- disk.sfdisk | 9 ++++ drivers/ata.c | 112 ++++++++++++++++++++++++++++++++++++++++ drivers/ata.h | 31 ++++++++--- 6 files changed, 164 insertions(+), 10 deletions(-) create mode 100644 disk.sfdisk diff --git a/Makefile b/Makefile index 4e37392..e547e82 100644 --- a/Makefile +++ b/Makefile @@ -34,8 +34,9 @@ fd.iso: kernel @printf "menuentry \"myos\" {\n\tmultiboot /boot/kernel\n}" > isodir/boot/grub/grub.cfg grub-mkrescue -o $@ isodir -disk.img: - qemu-img create -f qcow2 disk.img 32M +disk.img: disk.sfdisk + qemu-img create -f raw $@ 32M + sfdisk $@ < disk.sfdisk %.o:%.asm $(AS) $(ASFLAGS) -o $@ $< diff --git a/README.md b/README.md index 31a046d..5009c97 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ To generate iso image * `mtools xorriso (which is libisoburn on ArchLinux)` * gcc >= 6 + * sfdisk (util-linux) # Run it @@ -34,6 +35,17 @@ Then you can check some matos specific commands or pretty printing with `help user-defined` `info pretty-printer` (Should contains matos_pretty_printers) +# Change Disk partition + +You can either modify the disk.sfdisk file + +or + +modify the disk image woth your favorit tool (e.g. gparted) and re-generate disk.sfdisk + +sfdisk -d > disk.sfdisk + + # Features * VGA Driver @@ -45,3 +57,4 @@ Then you can check some matos specific commands or pretty printing with * Multithread (Full preempt) * Mutex * ATA + * basic userspace with syscall diff --git a/custom_gdb_extension.py b/custom_gdb_extension.py index 0479f02..dd405b2 100644 --- a/custom_gdb_extension.py +++ b/custom_gdb_extension.py @@ -16,11 +16,11 @@ class KthreadPrettyPrinter(object): line = gdb.execute(cmdline, to_string=True) #line = gdb.find_pc_line(int(cpuState["eip"].cast(gdb.lookup_type("long").pointer()).referenced_value())) currentThread = gdb.parse_and_eval("currentThread") - if self.val == currentThread: + if self.val.address == currentThread: result += "->" else: result += " " - result += "Addr: 0x%x, name: %s, state: %s, PC: %s" % (self.val, name, state, line) + result += "Addr: 0x%x, name: %s, state: %s, PC: %s" % (self.val.address, name, state, line) return result diff --git a/disk.sfdisk b/disk.sfdisk new file mode 100644 index 0000000..b1fe753 --- /dev/null +++ b/disk.sfdisk @@ -0,0 +1,9 @@ +label: dos +label-id: 0x9ec19bcc +device: disk.img +unit: sectors +sector-size: 512 + +disk.img1 : start= 2048, size= 10240, type=83 +disk.img2 : start= 12288, size= 10240, type=b +disk.img3 : start= 22528, size= 43008, type=e diff --git a/drivers/ata.c b/drivers/ata.c index 5bc8b1b..65a395e 100644 --- a/drivers/ata.c +++ b/drivers/ata.c @@ -1,9 +1,17 @@ +#include "alloc.h" #include "ata.h" #include "io.h" +#include "irq.h" #include "kernel.h" #include "klibc.h" +#include "list.h" #include "thread.h" +#define PART_TABLE_OFFSET 0x1BE + +static struct ata_partition *partitions; +static int nextPartitionId = 0; + // from // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data struct _IDENTIFY_DEVICE_DATA { @@ -378,6 +386,19 @@ struct _IDENTIFY_DEVICE_DATA { uint16_t CheckSum : 8; } __attribute__((packed)); +struct part_table_entry{ + uint32_t status:8; + uint32_t head_start:8; + uint32_t sector_start:6; + uint32_t cyl_start:10; + uint32_t type:8; + uint32_t head_end:8; + uint32_t sector_end:6; + uint32_t cyl_end:10; + uint32_t lba; + uint32_t size; +} __attribute__((packed)); + static struct ata_controller controllers[MAX_ATA_CONTROLLER] = {{ .id = 0, .base = 0x1F0, @@ -455,8 +476,91 @@ int ATAGetDeviceInfo(struct ata_device *dev) dev->sectors = deviceInfo->NumSectorsPerTrack; printf("Disk Detected[%d][%d]: %d Ko\n", ctl->id, dev->id, (dev->heads * dev->cyls * dev->sectors * DISK_SECTOR_SIZE) / 1024); + ATAReadPartition(dev); + return 0; } +const char *partTypeToStr(unsigned int type) +{ + switch (type) { + case PART_TYPE_EXTENDED: + return "Extended"; + case PART_TYPE_FAT16: + case PART_TYPE_FAT16_LBA: + return "FAT16"; + case PART_TYPE_FAT32: + case PART_TYPE_FAT32_LBA: + return "FAT32"; + case PART_TYPE_LINUX_SWAP: + return "Linux Swap"; + case PART_TYPE_LINUX: + return "Linux"; + default: + return "Unknown"; + } +} + +struct ata_partition *ATAGetPartition(int id) +{ + struct ata_partition *part; + int count; + list_foreach(partitions, part, count) + { + if (part->id == id) + return part; + } + + return NULL; +} + +struct ata_partition *ATAPartitionCreate(uint type, uint size, uint32_t lba, + struct ata_device *dev) +{ + struct ata_partition *part = + (struct ata_partition *)malloc(sizeof(struct ata_partition)); + if (part == NULL) + goto err; + + part->id = nextPartitionId++; + part->type = type; + part->size = size; + part->lba = lba; + part->device = dev; + + uint32_t flags; + disable_IRQs(flags); + + list_add_tail(partitions, part); + restore_IRQs(flags); + +err: + return part; +} + + +int ATAReadPartition(struct ata_device *dev) +{ + char buf[DISK_SECTOR_SIZE]; + int ret = ATAReadSector(dev, 0, 1, buf); + + if (ret) + return ret; + + struct part_table_entry *parts = (struct part_table_entry *)(buf + PART_TABLE_OFFSET); + for (int i = 0; i < 4; i++) { + if (parts[i].size == 0) + continue; + if (parts[i].type == PART_TYPE_EXTENDED) { + printf("Unsupported Partition extended\n"); + continue; + } + printf("Got partition %d type %s(0x%x) size %d kb lba 0x%x\n", i, + partTypeToStr(parts[i].type), parts[i].type, (parts[i].size * DISK_SECTOR_SIZE) >> 10, parts[i].lba); + ret++; + } + + return ret; +} int ATADetectController(struct ata_controller *controller) { @@ -488,12 +592,20 @@ int ATADetectController(struct ata_controller *controller) int ATAInit() { + list_init(partitions); for (uint i = 0; i < MAX_ATA_CONTROLLER; i++) { ATADetectController(&controllers[i]); } return 0; } +int ATAReadPartitionSector(struct ata_partition *part, int offset, uint nbSector, void *buf) +{ + int lba = part->lba + offset; + + return ATAReadSector(part->device, lba, nbSector, buf); +} + int ATAReadSector(struct ata_device *dev, int lba, uint nb_sector, void *buf) { struct ata_controller *ctl = dev->ctl; diff --git a/drivers/ata.h b/drivers/ata.h index c1b6e08..b6180e3 100644 --- a/drivers/ata.h +++ b/drivers/ata.h @@ -17,7 +17,7 @@ // cmd details // https://people.freebsd.org/~imp/asiabsdcon2015/works/d2161r5-ATAATAPI_Command_Set_-_3.pdf -#define ATA_PIO_CMD_IDENTIFY 0xEC /* get ATA params */ +#define ATA_PIO_CMD_IDENTIFY 0xEC /* get ATA params */ #define ATA_PIO_CMD_ATAPI_IDENTIFY 0xA1 /* get ATAPI params*/ #define ATA_PIO_CMD_READ 0x20 /* read command */ #define ATA_PIO_CMD_WRITE 0x30 /* write command */ @@ -26,11 +26,10 @@ #define ATA_PIO_CMD_SET_MULTI 0xC6 /* set multi size command */ #define ATA_PIO_CMD_PACKET_CMD 0xA0 /* set multi size command */ -#define ATA_PIO_DRIVE_IBM 0xA0 /* bits that must be set */ -#define ATA_PIO_DRIVE_LBA 0x40 /* use LBA ? */ -#define ATA_PIO_DRIVE_MASTER 0x00 /* select master */ -#define ATA_PIO_DRIVE_SLAVE 0x10 /* select slave */ - +#define ATA_PIO_DRIVE_IBM 0xA0 /* bits that must be set */ +#define ATA_PIO_DRIVE_LBA 0x40 /* use LBA ? */ +#define ATA_PIO_DRIVE_MASTER 0x00 /* select master */ +#define ATA_PIO_DRIVE_SLAVE 0x10 /* select slave */ #define ATA_PIO_ERROR_ADDR_MARK_NOT_FOUND 0 #define ATA_PIO_ERROR_TRACK_ZERO_NOT_FOUND 1 @@ -55,6 +54,14 @@ #define DISK_SECTOR_SIZE 512 +#define PART_TYPE_EXTENDED 0x5 +#define PART_TYPE_FAT16 0x6 +#define PART_TYPE_FAT16_LBA 0xe +#define PART_TYPE_FAT32 0xb +#define PART_TYPE_FAT32_LBA 0xc +#define PART_TYPE_LINUX_SWAP 0x82 +#define PART_TYPE_LINUX 0x83 + typedef enum { ATA_DEV_UNKNOWN, ATA_DEV_PATA, @@ -83,7 +90,19 @@ struct ata_controller { int last_device_used; }; +struct ata_partition { + int id; + uint type; + uint size; + uint32_t lba; + struct ata_device *device; + struct ata_partition *prev, *next; +}; + int ATAInit(); +int ATAReadPartitionSector(struct ata_partition *part, int offset, uint nbSector, void *buf); int ATAReadSector(struct ata_device *dev, int lba, uint nbSector, void *buf); int ATAWriteSector(struct ata_device *dev, int lba, uint nbSector, void *buf); struct ata_device *ATAGetDevice(int ctlId, int devId); +int ATAReadPartition(struct ata_device *dev); +struct ata_partition *ATAGetPartition(int id);