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:
2021-02-09 22:47:35 +01:00
parent 9440fae968
commit 2ac0da6574
16 changed files with 467 additions and 106 deletions

View File

@@ -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) {

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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
View 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
View 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
View 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
View 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
View 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
View 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

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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];
}

View File

@@ -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);