feat: setup structure for block devices
added ide block device added mbr block device driver started fat block device driver reordered boot start timer before pci/ide/etc. enable interrupts earlier fixed exception from ide controller cleanup code more printfs
This commit is contained in:
@@ -3,11 +3,11 @@
|
||||
//
|
||||
|
||||
#include "isr.h"
|
||||
#include <kprint.h>
|
||||
|
||||
#include <cpu/idt.h>
|
||||
#include <libc/libc.h>
|
||||
#include <drivers/ports.h>
|
||||
#include <libc/kprintf.h>
|
||||
|
||||
#define PIC_END_OF_INTERRUPT 0x20
|
||||
|
||||
@@ -119,13 +119,7 @@ char *exception_messages[] = {
|
||||
};
|
||||
|
||||
void isr_handler(registers_t r) {
|
||||
kprint("received interrupt: ");
|
||||
char s[3];
|
||||
itoa(r.int_no, s, 10);
|
||||
kprint(s);
|
||||
kprint("\n");
|
||||
kprint(exception_messages[r.int_no]);
|
||||
kprint("\n");
|
||||
printf("Received interrupt: %d - %s\n", r.int_no, exception_messages[r.int_no]);
|
||||
}
|
||||
|
||||
void register_interrupt_handler(u8 n, isr_t handler) {
|
||||
|
||||
@@ -40,7 +40,7 @@ static void timer_callback(registers_t regs) {
|
||||
|
||||
void sleep(u32 milliseconds) {
|
||||
u32 done = tick + milliseconds;
|
||||
while (done != milliseconds) {
|
||||
while (tick != done) {
|
||||
k_wait_for_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <libk.h>
|
||||
#include <cpu/timer.h>
|
||||
#include <libc/kprintf.h>
|
||||
#include <fs/blockdev.h>
|
||||
#include <mem/mem.h>
|
||||
|
||||
#define ATA_SR_BSY 0x80 // Busy
|
||||
#define ATA_SR_DRDY 0x40 // Drive ready
|
||||
@@ -128,6 +130,11 @@ struct ide_device {
|
||||
unsigned char model[41]; // Model in string.
|
||||
} ide_devices[4];
|
||||
|
||||
typedef struct {
|
||||
u8 device_number: 2;
|
||||
u8 print_error: 1;
|
||||
} ide_block_device_info;
|
||||
|
||||
u8 ide_read(u8 channel, u8 reg);
|
||||
|
||||
void ide_write(u8 channel, u8 reg, u8 data);
|
||||
@@ -256,48 +263,54 @@ unsigned char ide_print_error(unsigned int drive, unsigned char err) {
|
||||
|
||||
kprint("IDE:");
|
||||
if (err == 1) {
|
||||
kprint("- Device Fault\n ");
|
||||
kprint("- Device Fault ");
|
||||
err = 19;
|
||||
} else if (err == 2) {
|
||||
unsigned char st = ide_read(ide_devices[drive].channel, ATA_REG_ERROR);
|
||||
if (st & ATA_ER_AMNF) {
|
||||
kprint("- No Address Mark Found\n ");
|
||||
kprint("- No Address Mark Found - ");
|
||||
err = 7;
|
||||
}
|
||||
if (st & ATA_ER_TK0NF) {
|
||||
kprint("- No Media or Media Error\n ");
|
||||
kprint("- No Media or Media Error - ");
|
||||
err = 3;
|
||||
}
|
||||
if (st & ATA_ER_ABRT) {
|
||||
kprint("- Command Aborted\n ");
|
||||
kprint("- Command Aborted - ");
|
||||
err = 20;
|
||||
}
|
||||
if (st & ATA_ER_MCR) {
|
||||
kprint("- No Media or Media Error\n ");
|
||||
kprint("- No Media or Media Error - ");
|
||||
err = 3;
|
||||
}
|
||||
if (st & ATA_ER_IDNF) {
|
||||
kprint("- ID mark not Found\n ");
|
||||
kprint("- ID mark not Found - ");
|
||||
err = 21;
|
||||
}
|
||||
if (st & ATA_ER_MC) {
|
||||
kprint("- No Media or Media Error\n ");
|
||||
kprint("- No Media or Media Error - ");
|
||||
err = 3;
|
||||
}
|
||||
if (st & ATA_ER_UNC) {
|
||||
kprint("- Uncorrectable Data Error\n ");
|
||||
kprint("- Uncorrectable Data Error - ");
|
||||
err = 22;
|
||||
}
|
||||
if (st & ATA_ER_BBK) {
|
||||
kprint("- Bad Sectors\n ");
|
||||
kprint("- Bad Sectors - ");
|
||||
err = 13;
|
||||
}
|
||||
} else if (err == 3) {
|
||||
kprint("- Reads Nothing\n ");
|
||||
kprint("- Reads Nothing - ");
|
||||
err = 23;
|
||||
} else if (err == 4) {
|
||||
kprint("- Write Protected\n ");
|
||||
kprint("- Write Protected - ");
|
||||
err = 8;
|
||||
} else if (err & 0xF0) {
|
||||
if (err == 0xF1) {
|
||||
kprint("- Unsupported operation by driver - ");
|
||||
} else {
|
||||
kprint(" - Unknown driver error - ");
|
||||
}
|
||||
}
|
||||
printf(" - [%s %s] %s\n",
|
||||
((const char *[]) {"Primary", "Secondary"}[ide_devices[drive].channel]),
|
||||
@@ -313,7 +326,7 @@ u8 ide_pci_initialize(pci_device *device);
|
||||
const pci_driver ide_pci_driver = {
|
||||
.name = "pci-ide",
|
||||
.description = "Default PCI IDE Driver",
|
||||
.order = 0xFF, // let other drivers precede if they can
|
||||
.order = 0xFF, // let other block_dev_drivers precede if they can
|
||||
.pci_use_subclass = true,
|
||||
.pci_class = PCI_CLASS_MASS_STORAGE,
|
||||
.pci_subclass = PCI_SUB_CLASS_IDE,
|
||||
@@ -381,6 +394,43 @@ bool ide_pci_init_channels(pci_device *device) {
|
||||
return true;
|
||||
}
|
||||
|
||||
u8 ide_block_dev_access(const block_device *device, u8 direction, u32 lba, u8 sectors, void *target) {
|
||||
ide_block_device_info *info = device->device_info;
|
||||
u8 result = ide_access(direction, info->device_number, lba, sectors, target);
|
||||
if (result != 0) {
|
||||
if (info->print_error) {
|
||||
ide_print_error(info->device_number, result);
|
||||
}
|
||||
return BLOCK_DEV_ACCESS_ERR;
|
||||
}
|
||||
return BLOCK_DEV_ACCESS_OK;
|
||||
}
|
||||
|
||||
void ide_register_block_devices() {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (!ide_devices[i].reserved) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ide_block_device_info *info = malloc(sizeof(ide_block_device_info)); // todo free for this one
|
||||
info->device_number = i;
|
||||
info->print_error = 1;
|
||||
|
||||
block_device device = {
|
||||
.flags.present = 1,
|
||||
.flags.root_device = 1,
|
||||
.device_info = info,
|
||||
.num_lba = ide_devices[i].size,
|
||||
.block_size = 0x200,
|
||||
.access = ide_block_dev_access,
|
||||
};
|
||||
sprintf(device.identifier, "ide%d", i);
|
||||
|
||||
block_dev_register(&device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u8 ide_pci_initialize(pci_device *device) {
|
||||
|
||||
if (!ide_pci_init_channels(device)) {
|
||||
@@ -393,7 +443,7 @@ u8 ide_pci_initialize(pci_device *device) {
|
||||
|
||||
int count = 0;
|
||||
// 3- Detect ATA-ATAPI Devices:
|
||||
for (int i = 0; i < 2; i++)
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
|
||||
unsigned char err = 0, type = IDE_ATA, status;
|
||||
@@ -467,6 +517,8 @@ u8 ide_pci_initialize(pci_device *device) {
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
ide_register_block_devices();
|
||||
|
||||
return PCI_INIT_OK;
|
||||
}
|
||||
@@ -543,9 +595,6 @@ u8 ide_read_ata_access(u8 direction, u8 drive, u32 lba, u8 numsects, void *targe
|
||||
// wait for the drive to have time for us
|
||||
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY) {}
|
||||
|
||||
// clear error
|
||||
ide_write(channel, ATA_REG_ERROR, 0);
|
||||
|
||||
if (lba_mode == 0) {
|
||||
ide_write(channel,
|
||||
ATA_REG_HDDEVSEL,
|
||||
@@ -618,11 +667,11 @@ u8 ide_read_ata_access(u8 direction, u8 drive, u32 lba, u8 numsects, void *targe
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 ide_read_access(u8 direction, u8 drive, u32 lba, u8 numsects, void *target) {
|
||||
u8 ide_access(u8 direction, u8 drive, u32 lba, u8 numsects, void *target) {
|
||||
if (drive > 3
|
||||
|| ide_devices[drive].reserved == 1
|
||||
|| ide_devices[drive].reserved == 0
|
||||
|| ide_devices[drive].type == IDE_ATAPI) {
|
||||
k_panics("Not supported device read operation");
|
||||
return 0xF1;
|
||||
}
|
||||
return ide_read_ata_access(direction, drive, lba, numsects, target);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
void ide_register();
|
||||
|
||||
u8 ide_read_access(u8 direction, u8 drive, u32 lba, u8 numsects, void *target);
|
||||
u8 ide_access(u8 direction, u8 drive, u32 lba, u8 numsects, void *target);
|
||||
|
||||
void ide_print_devices();
|
||||
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
//
|
||||
#include "keyboard.h"
|
||||
|
||||
#include <kprint.h>
|
||||
#include <drivers/ports.h>
|
||||
#include <cpu/isr.h>
|
||||
#include <libc/libc.h>
|
||||
#include <libc/stdbool.h>
|
||||
#include <libc/ringqueue.h>
|
||||
#include <mem/mem.h>
|
||||
@@ -27,28 +25,6 @@ const char scancode_map_uppercase[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
//
|
||||
//char scancodes_ascii[] = {
|
||||
// 0, 0,
|
||||
// '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0,
|
||||
// 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0,
|
||||
// 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
|
||||
// 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0,
|
||||
// '*',
|
||||
// 0, ' ',
|
||||
// 0,
|
||||
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F1-F10
|
||||
// 0, 0,
|
||||
// '7', '8', '9', '-',
|
||||
// '4', '5', '6', '+',
|
||||
// '1', '2', '3',
|
||||
// '0', 0,
|
||||
// 0, // sysrq
|
||||
// 0, 0, // weird
|
||||
// 0, 0, // F11 F12
|
||||
// // weid
|
||||
//};
|
||||
|
||||
struct {
|
||||
u8 shift: 1;
|
||||
u8 ctrl: 1;
|
||||
@@ -58,11 +34,9 @@ struct {
|
||||
|
||||
void *keyboard_event_buffer = NULL;
|
||||
|
||||
char *MSG_KEY = "Clicked on key 'x'\n";
|
||||
|
||||
char getc() {
|
||||
while (true) {
|
||||
KeyEvent* event = get_next_event();
|
||||
KeyEvent *event = get_next_event();
|
||||
char retval = 0;
|
||||
if (event == NULL) {
|
||||
goto _getc_end;
|
||||
@@ -154,7 +128,6 @@ static void keyboard_callback(registers_t regs) {
|
||||
}
|
||||
unsigned char scancode = port_byte_in(PORT_PS2_DATA);
|
||||
publish_key_event(scancode);
|
||||
// print_scancode(scancode);
|
||||
}
|
||||
|
||||
void init_keyboard() {
|
||||
@@ -165,25 +138,3 @@ void init_keyboard() {
|
||||
keyboard_state.extended = 0;
|
||||
keyboard_event_buffer = create_buffer(256, sizeof(KeyEvent));
|
||||
}
|
||||
|
||||
//void print_scancode(unsigned char scancode) {
|
||||
// char msg[256];
|
||||
// char release = 0;
|
||||
// if (scancode > 0x80) {
|
||||
// // release
|
||||
// release = 1;
|
||||
// scancode -= 0x80;
|
||||
// }
|
||||
// char code = scancodes_ascii[scancode];
|
||||
// if (code == 0) {
|
||||
// // special
|
||||
// } else {
|
||||
// if (release && code > 0x60 && code < 0x7B) {
|
||||
// code -= 0x20; // to lowercase
|
||||
// }
|
||||
//
|
||||
// strcpy(msg, MSG_KEY);
|
||||
// msg[strlen(msg) - 3] = code;
|
||||
// kprint(msg);
|
||||
// }
|
||||
//}
|
||||
92
kernel/fs/blockdev.c
Normal file
92
kernel/fs/blockdev.c
Normal file
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// Created by rick on 06-02-21.
|
||||
//
|
||||
|
||||
#include <libc/libc.h>
|
||||
#include <libk.h>
|
||||
#include <mem/mem.h>
|
||||
#include <libc/kprintf.h>
|
||||
#include "blockdev.h"
|
||||
|
||||
#define MAX_BLOCK_DEVS 64
|
||||
#define MAX_BLOCK_DRIVERS 64
|
||||
|
||||
int last_block_dev = 0;
|
||||
block_device block_devices[MAX_BLOCK_DEVS];
|
||||
int last_block_driver = 0;
|
||||
block_dev_driver block_dev_drivers[MAX_BLOCK_DRIVERS];
|
||||
|
||||
u8 block_dev_register_driver(block_dev_driver *driver) {
|
||||
if (last_block_dev >= MAX_BLOCK_DEVS - 1) {
|
||||
return BLOCK_DEV_REGISTER_DRIVER_FULL;
|
||||
}
|
||||
|
||||
memcpy((u8 *) &block_dev_drivers[last_block_driver++], (const u8 *) driver, sizeof(block_dev_drivers));
|
||||
return BLOCK_DEV_REGISTER_DRIVER_OK;
|
||||
}
|
||||
|
||||
u8 block_dev_register(block_device *device) {
|
||||
if (last_block_dev >= MAX_BLOCK_DEVS - 1) {
|
||||
return BLOCK_DEV_REGISTER_FULL;
|
||||
}
|
||||
|
||||
memcpy((u8 *) &block_devices[last_block_dev++], (const u8 *) device, sizeof(block_device));
|
||||
return BLOCK_DEV_REGISTER_OK;
|
||||
}
|
||||
|
||||
void block_dev_free(block_device *device) {
|
||||
//todo
|
||||
k_panics("block dev free not supported");
|
||||
}
|
||||
|
||||
int block_dev_num_not_scanned() {
|
||||
int not_scanned = 0;
|
||||
for (int i = 0; i < last_block_dev; ++i) {
|
||||
if (block_devices[i].flags.present && !block_devices[i].flags.scanned) not_scanned++;
|
||||
}
|
||||
return not_scanned;
|
||||
}
|
||||
|
||||
void block_dev_scan() {
|
||||
int c_last_block_dev = last_block_dev;
|
||||
for (int i = 0; i < c_last_block_dev; ++i) {
|
||||
if (block_devices[i].flags.scanned || !block_devices[i].flags.present) continue;
|
||||
u8 *lba0 = malloc(block_devices[i].block_size*4);
|
||||
u8 read_result = block_devices[i].access(&block_devices[i], BLOCK_DEV_DIRECTION_READ, 0, 1, lba0);
|
||||
if (read_result != BLOCK_DEV_ACCESS_OK) {
|
||||
block_devices[i].flags.unreadable = 1;
|
||||
goto _block_dev_scan_free;
|
||||
}
|
||||
for (int j = 0; j < last_block_driver; ++j) {
|
||||
// validate if driver is appropriate at all
|
||||
// don't use a root device driver (i.e. mbr) for a non-root device
|
||||
if (block_dev_drivers[j].flags.root_only && !block_devices[i].flags.root_device) continue;
|
||||
|
||||
// let the driver test the disk
|
||||
u8 driver_result = block_dev_drivers[j].check_device(&block_devices[i], lba0);
|
||||
if (driver_result == BLOCK_DEV_DRIVER_CHECK_OK) {
|
||||
block_devices[i].driver = &block_dev_drivers[j];
|
||||
block_devices[i].flags.driver_installed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_block_dev_scan_free:
|
||||
free(lba0);
|
||||
block_devices[i].flags.scanned = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void block_dev_scan_repeat() {
|
||||
while (block_dev_num_not_scanned() > 0) {
|
||||
block_dev_scan();
|
||||
}
|
||||
}
|
||||
|
||||
void block_dev_print_info() {
|
||||
printf("Block devices:\n");
|
||||
for (int i = 0; i < last_block_dev; ++i) {
|
||||
printf("-%s driver: %s\n",
|
||||
block_devices[i].identifier,
|
||||
block_devices[i].flags.driver_installed ? block_devices[i].driver->name : "n/a");
|
||||
}
|
||||
}
|
||||
71
kernel/fs/blockdev.h
Normal file
71
kernel/fs/blockdev.h
Normal file
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// Created by rick on 06-02-21.
|
||||
//
|
||||
|
||||
#ifndef NEW_KERNEL_BLOCKDEV_H
|
||||
#define NEW_KERNEL_BLOCKDEV_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define BLOCK_DEV_ACCESS_OK 0
|
||||
#define BLOCK_DEV_ACCESS_ERR 1
|
||||
|
||||
#define BLOCK_DEV_DIRECTION_READ 0
|
||||
#define BLOCK_DEV_DIRECTION_WRITE 1
|
||||
|
||||
#define BLOCK_DEV_DRIVER_CHECK_OK 0
|
||||
#define BLOCK_DEV_DRIVER_CHECK_NO_MATCH 1
|
||||
|
||||
#define BLOCK_DEV_REGISTER_DRIVER_OK 0
|
||||
#define BLOCK_DEV_REGISTER_DRIVER_FULL 1
|
||||
|
||||
#define BLOCK_DEV_REGISTER_OK 0
|
||||
#define BLOCK_DEV_REGISTER_FULL 1
|
||||
|
||||
|
||||
typedef struct block_device block_device;
|
||||
|
||||
typedef u8 (*block_device_driver_check_device)(const block_device *device, u8 *first_sector);
|
||||
|
||||
typedef u8 (*block_device_driver_free)(const block_device *device);
|
||||
|
||||
typedef u8 (*block_device_access)(const block_device *device, u8 direction, u32 lba, u8 sectors, void *target);
|
||||
|
||||
|
||||
typedef struct {
|
||||
char name[16];
|
||||
struct {
|
||||
u8 root_only: 1;
|
||||
} flags;
|
||||
block_device_driver_check_device check_device;
|
||||
block_device_driver_free free_device;
|
||||
} block_dev_driver;
|
||||
|
||||
typedef struct block_device {
|
||||
struct {
|
||||
u8 present: 1;
|
||||
u8 scanned: 1;
|
||||
u8 unreadable: 1;
|
||||
u8 root_device: 1;
|
||||
u8 driver_installed: 1;
|
||||
} flags;
|
||||
char identifier[16];
|
||||
u32 num_lba;
|
||||
u16 block_size;
|
||||
block_device_access access;
|
||||
block_dev_driver *driver;
|
||||
void *device_info; // pointer to driver defined structure
|
||||
// todo device info
|
||||
} block_device;
|
||||
|
||||
u8 block_dev_register_driver(block_dev_driver *driver);
|
||||
|
||||
u8 block_dev_register(block_device *device);
|
||||
|
||||
void block_dev_free(block_device *device);
|
||||
|
||||
void block_dev_scan_repeat();
|
||||
|
||||
void block_dev_print_info();
|
||||
|
||||
#endif //NEW_KERNEL_BLOCKDEV_H
|
||||
53
kernel/fs/fat.c
Normal file
53
kernel/fs/fat.c
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// Created by rick on 07-02-21.
|
||||
//
|
||||
|
||||
#include "fat.h"
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
u8 jump[3];
|
||||
char oem_identifier[8];
|
||||
u16 bytes_per_sector;
|
||||
u8 sectors_per_cluster;
|
||||
u16 reserved_sectors;
|
||||
u8 fats;
|
||||
u16 directories;
|
||||
u16 total_sectors;
|
||||
u8 media_descriptor;
|
||||
u16 sectors_per_fat;
|
||||
u16 sectors_per_track;
|
||||
u16 heads_sides;
|
||||
u32 hidden_sectors;
|
||||
u32 large_sector_count;
|
||||
} bpb;
|
||||
union {
|
||||
struct {
|
||||
u8 drive_number;
|
||||
u8 flags;
|
||||
u8 signature;
|
||||
u32 serial;
|
||||
u8 label[11];
|
||||
u8 system_id[8];
|
||||
} ebr_12_16;
|
||||
struct {
|
||||
u32 sectors_per_fat;
|
||||
u16 flags;
|
||||
u16 fat_version;
|
||||
u32 root_directory;
|
||||
u16 fs_info;
|
||||
u16 backup_boot;
|
||||
u8 reserved[12];
|
||||
u8 drive_number;
|
||||
u8 flags_nt;
|
||||
u8 signature;
|
||||
u32 serial;
|
||||
u8 label[11];
|
||||
u8 system_id[8];
|
||||
} ebr_32;
|
||||
};
|
||||
} fat_bpb;
|
||||
|
||||
// steal validation code from here https://github.com/torvalds/linux/blob/fcadab740480e0e0e9fa9bd272acd409884d431a/fs/fat/inode.c#L1456
|
||||
8
kernel/fs/fat.h
Normal file
8
kernel/fs/fat.h
Normal file
@@ -0,0 +1,8 @@
|
||||
//
|
||||
// Created by rick on 07-02-21.
|
||||
//
|
||||
|
||||
#ifndef NEW_KERNEL_FAT_H
|
||||
#define NEW_KERNEL_FAT_H
|
||||
|
||||
#endif //NEW_KERNEL_FAT_H
|
||||
109
kernel/fs/mbr.c
Normal file
109
kernel/fs/mbr.c
Normal file
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// Created by rick on 06-02-21.
|
||||
//
|
||||
|
||||
#include "mbr.h"
|
||||
#include <types.h>
|
||||
#include <drivers/ide.h>
|
||||
#include <mem/mem.h>
|
||||
#include <libc/kprintf.h>
|
||||
#include <fs/blockdev.h>
|
||||
|
||||
typedef struct {
|
||||
u8 bootable;
|
||||
u8 starting_head;
|
||||
u8 starting_sector: 6;
|
||||
u16 starting_cylinder: 10;
|
||||
u8 system_id;
|
||||
u8 ending_head;
|
||||
u8 ending_sector: 6;
|
||||
u16 ending_cylinder: 10;
|
||||
u32 start_lba;
|
||||
u32 num_lbas;
|
||||
} __attribute((packed)) mbr_partition_table_entry;
|
||||
|
||||
typedef struct {
|
||||
u32 unique_id;
|
||||
u16 reserved;
|
||||
mbr_partition_table_entry entries[4];
|
||||
u8 signature[2];
|
||||
} __attribute((packed)) mbr_table;
|
||||
|
||||
typedef struct {
|
||||
const block_device *device;
|
||||
u32 start_lba;
|
||||
} mbr_block_driver_info;
|
||||
|
||||
u8 mbr_block_dev_access(const block_device *device, u8 direction, u32 lba, u8 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 u32 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);
|
||||
}
|
||||
|
||||
u8 mbr_check_device(const block_device *device, u8* first_sector) {
|
||||
mbr_table *table = (mbr_table *) &first_sector[512 - 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;
|
||||
}
|
||||
|
||||
block_dev_driver mbr_driver = {
|
||||
.name = "mbr",
|
||||
.flags.root_only = 1,
|
||||
.check_device = mbr_check_device,
|
||||
.free_device = NULL, // todo
|
||||
};
|
||||
|
||||
void mbr_register_block_driver() {
|
||||
block_dev_register_driver(&mbr_driver);
|
||||
}
|
||||
|
||||
void mbr_read_from_ide(u8 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);
|
||||
}
|
||||
14
kernel/fs/mbr.h
Normal file
14
kernel/fs/mbr.h
Normal file
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// Created by rick on 06-02-21.
|
||||
//
|
||||
|
||||
#ifndef NEW_KERNEL_MBR_H
|
||||
#define NEW_KERNEL_MBR_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
void mbr_register_block_driver();
|
||||
|
||||
void mbr_read_from_ide(u8 ide_drive);
|
||||
|
||||
#endif //NEW_KERNEL_MBR_H
|
||||
@@ -15,13 +15,16 @@
|
||||
#include <drivers/pci.h>
|
||||
#include <drivers/ide.h>
|
||||
#include <libc/kprintf.h>
|
||||
#include <fs/mbr.h>
|
||||
#include <fs/blockdev.h>
|
||||
|
||||
#define BOOTLOADER_NAME_MAX_LENGTH 64
|
||||
#define CMDLINE_MAX_LENGTH 256
|
||||
|
||||
const char *msg_booted = "Booted Successfully!\n";
|
||||
const char *newline = "\n";
|
||||
const char *msg_unknown_command = "Unknown command: ";
|
||||
const int version_major = 0,
|
||||
version_minor = 0,
|
||||
version_patch = 1;
|
||||
|
||||
char bootloader_name[BOOTLOADER_NAME_MAX_LENGTH];
|
||||
char cmdline[CMDLINE_MAX_LENGTH];
|
||||
@@ -67,8 +70,7 @@ void help(const char* arg) {
|
||||
}
|
||||
|
||||
void echo(const char *arg) {
|
||||
kprint(arg);
|
||||
kprint(newline);
|
||||
printf("%s\n", arg);
|
||||
}
|
||||
|
||||
void print(const char *arg) {
|
||||
@@ -85,19 +87,19 @@ void print(const char *arg) {
|
||||
} else if (strcmp(arg, "ide") == 0) {
|
||||
ide_print_devices();
|
||||
} else {
|
||||
kprint("Unknown print ");
|
||||
kprint(arg);
|
||||
kprint(newline);
|
||||
printf("Unknown print %s\n", arg);
|
||||
}
|
||||
}
|
||||
|
||||
void ide(const char* arg) {
|
||||
if (strcmp(arg, "devices") == 0) {
|
||||
if (strcmp(arg, "block_devices") == 0) {
|
||||
block_dev_print_info();
|
||||
} else if (strcmp(arg, "ide_devices") == 0) {
|
||||
ide_print_devices();
|
||||
} else if (strcmp(arg, "mbr") == 0) {
|
||||
mbr_read_from_ide(0);
|
||||
} else {
|
||||
kprint("Unknown print ");
|
||||
kprint(arg);
|
||||
kprint(newline);
|
||||
printf("Unknown print %s\n", arg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +144,14 @@ void init_pci_system() {
|
||||
pci_init_drivers();
|
||||
}
|
||||
|
||||
void init_block_devices() {
|
||||
// register drivers
|
||||
mbr_register_block_driver();
|
||||
|
||||
// scan
|
||||
block_dev_scan_repeat();
|
||||
}
|
||||
|
||||
void kmain(multiboot_info_t *multiboot_info) {
|
||||
isr_install();
|
||||
vga_clear_screen();
|
||||
@@ -153,22 +163,18 @@ void kmain(multiboot_info_t *multiboot_info) {
|
||||
store_bootloader_info(multiboot_info);
|
||||
init_mmap(multiboot_info);
|
||||
|
||||
init_pci_system();
|
||||
|
||||
kprint(msg_booted);
|
||||
kprint(newline);
|
||||
|
||||
// init done, enable interrupts
|
||||
__asm__ __volatile__("sti");
|
||||
// init timer for future task switching
|
||||
init_timer(1000);
|
||||
// setup PS/2 keyboard
|
||||
init_keyboard();
|
||||
init_pci_system();
|
||||
init_block_devices();
|
||||
|
||||
printf("%s v%d.%d.%d\n", msg_booted, version_major, version_minor, version_patch);
|
||||
// print_gdt();
|
||||
|
||||
// u8* tmp = malloc(4096);
|
||||
// ide_read_access(0, 0, 0, 16, tmp);
|
||||
// ide_access(0, 0, 0, 16, tmp);
|
||||
|
||||
// enter main loop
|
||||
while (true) {
|
||||
@@ -183,9 +189,7 @@ void main_loop() {
|
||||
int test_index = 0;
|
||||
while (true) {
|
||||
if (cmd_handlers[test_index].cmd == 0) {
|
||||
kprint(msg_unknown_command);
|
||||
kprint(msg);
|
||||
kprint(newline);
|
||||
printf("Unknown command: %s\n", msg);
|
||||
break;
|
||||
}
|
||||
if (strcmp(cmd_handlers[test_index].cmd, msg) == 0) {
|
||||
|
||||
@@ -74,11 +74,22 @@ u32 vasprintf(char *buf, const char *fmt, va_list args) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void printf(const char *fmt, ...) {
|
||||
int printf(const char *fmt, ...) {
|
||||
int result;
|
||||
char buf[1024] = {-1};
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vasprintf(buf, fmt, args);
|
||||
result = vasprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
kprint(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sprintf(char* target, const char*fmt, ...) {
|
||||
int result;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
result = vasprintf(target, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef NEW_KERNEL_KPRINTF_H
|
||||
#define NEW_KERNEL_KPRINTF_H
|
||||
|
||||
void printf(const char *fmt, ...);
|
||||
int printf(const char *fmt, ...);
|
||||
|
||||
int sprintf(char *target, const char *fmt, ...);
|
||||
|
||||
#endif //NEW_KERNEL_KPRINTF_H
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
* Author: rick
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include "libc.h"
|
||||
|
||||
int memcpy(char *dst, char *src, int amount) {
|
||||
int memcpy(u8 *dst, const u8 *src, int amount) {
|
||||
for (int i = 0; i < amount; i++) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
#ifndef KERNEL_LIBC_LIBC_H_
|
||||
#define KERNEL_LIBC_LIBC_H_
|
||||
|
||||
int memcpy(char *dst, char *src, int amount);
|
||||
#include <types.h>
|
||||
|
||||
int memcpy(u8 *dst, const u8 *src, int amount);
|
||||
|
||||
int memset(char *dst, char data, int amount);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user