mirror of
https://github.com/Tom-on64/kern.git
synced 2026-11-03 18:22:22 +00:00
Began work FAT32 drivers in KBOOT
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
#ifndef ATTR_H
|
#ifndef _DEFS_H
|
||||||
#define ATTR_H
|
#define _DEFS_H
|
||||||
|
|
||||||
#define __packed __attribute__((packed))
|
#define __packed __attribute__((packed))
|
||||||
#define __naked __attribute__((naked))
|
#define __naked __attribute__((naked))
|
||||||
#define __section(_sect) __attribute__((section(_sect)))
|
#define __section(_sect) __attribute__((section(_sect)))
|
||||||
#define noreturn __attribute__((noreturn))
|
#define noreturn __attribute__((noreturn))
|
||||||
|
#define sizeof_array(_a) (sizeof(_a) / sizeof(_a[0]))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+16
-2
@@ -19,6 +19,20 @@ void readSectors(uint32_t lba, size_t count, void* dst) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO */
|
void writeSectors(uint32_t lba, size_t count, void* src) {
|
||||||
void writeSectors(uint32_t lba, size_t count, void* src) {}
|
outb(PIO_PORT + 6, ((lba >> 24) & 0x0f) | 0xe0);
|
||||||
|
outb(PIO_PORT + 2, count);
|
||||||
|
outb(PIO_PORT + 3, lba & 0xff);
|
||||||
|
outb(PIO_PORT + 4, (lba >> 8) & 0xff);
|
||||||
|
outb(PIO_PORT + 5, (lba >> 16) & 0xff);
|
||||||
|
outb(PIO_PORT + 7, PIO_CMD_WRITE);
|
||||||
|
|
||||||
|
uint16_t* buf = (uint16_t*)src;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
while (inb(PIO_PORT + 7) & (1 << 7)); // Wait until BSY is cleared
|
||||||
|
for (size_t j = 0; j < SECTOR_SIZE / 2; j++) outw(PIO_PORT, *buf++);
|
||||||
|
for (uint8_t wait = 0; wait < 4; wait++) inb(PIO_ALT_STATUS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -2,7 +2,7 @@
|
|||||||
#define DISK_H
|
#define DISK_H
|
||||||
|
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include "attr.h"
|
#include "defs.h"
|
||||||
|
|
||||||
#define SECTOR_SIZE 512
|
#define SECTOR_SIZE 512
|
||||||
#define PIO_PORT 0x1f0
|
#define PIO_PORT 0x1f0
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#define BOOTABLE 0x80
|
#define BOOTABLE 0x80
|
||||||
|
|
||||||
|
#define LBA_TO_OFFSET(_a) ((_a) * SECTOR_SIZE)
|
||||||
|
|
||||||
struct partition {
|
struct partition {
|
||||||
uint8_t bootable;
|
uint8_t bootable;
|
||||||
uint8_t startCHS[3];
|
uint8_t startCHS[3];
|
||||||
|
|||||||
+31
-14
@@ -1,24 +1,46 @@
|
|||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
|
#include "fat32.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "attr.h"
|
#include "defs.h"
|
||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "kbd.h"
|
#include "kbd.h"
|
||||||
|
|
||||||
|
noreturn void panic() {
|
||||||
|
setAttr(0x04);
|
||||||
|
text(COLS/2, ROWS/2, "[ PANIC ]");
|
||||||
|
while (1) __asm__ volatile ("cli; hlt");
|
||||||
|
}
|
||||||
|
|
||||||
void drawPartitions(struct MBR* mbr, uint8_t sel);
|
void drawPartitions(struct MBR* mbr, uint8_t sel);
|
||||||
void partitonInfo(struct partition* part);
|
void partitonInfo(struct partition* part);
|
||||||
|
struct partition* menu(struct MBR* mbr);
|
||||||
|
|
||||||
__section("entry")
|
__section("entry")
|
||||||
noreturn void main() {
|
noreturn void main() {
|
||||||
keyboardInit();
|
keyboardInit();
|
||||||
|
|
||||||
struct MBR mbr;
|
struct MBR mbr;
|
||||||
readSectors(0, 1, &mbr);
|
readSectors(0, 1, &mbr);
|
||||||
|
struct partition* bootpart = menu(&mbr);
|
||||||
|
|
||||||
|
setAttr(0x0f);
|
||||||
|
cls();
|
||||||
|
showCursor();
|
||||||
|
|
||||||
|
if (fat32_init(bootpart) != 0) {
|
||||||
|
setAttr(0x0c);
|
||||||
|
printf("Failed to initialize FAT32.");
|
||||||
|
panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct partition* menu(struct MBR* mbr) {
|
||||||
// Select bootable partition by default
|
// Select bootable partition by default
|
||||||
uint8_t selected = 0;
|
uint8_t selected = 0;
|
||||||
for (size_t i = 0; i < 4; i++) {
|
for (size_t i = 0; i < 4; i++) {
|
||||||
if (mbr.partitions[i].bootable != BOOTABLE) continue;
|
if (mbr->partitions[i].bootable != BOOTABLE) continue;
|
||||||
selected = i;
|
selected = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -31,14 +53,14 @@ noreturn void main() {
|
|||||||
hline(0, 2, COLS);
|
hline(0, 2, COLS);
|
||||||
setAttr(0x02);
|
setAttr(0x02);
|
||||||
text(COLS / 2, 1, "KBOOT");
|
text(COLS / 2, 1, "KBOOT");
|
||||||
drawPartitions(&mbr, selected);
|
drawPartitions(mbr, selected);
|
||||||
partitonInfo(&mbr.partitions[selected]);
|
partitonInfo(&mbr->partitions[selected]);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
// Check for up/down arrow keys or enter
|
// Check for up/down arrow keys or enter
|
||||||
uint8_t scancode = getScancode();
|
uint8_t scancode = getScancode();
|
||||||
if (scancode == SC_ENTER) { // Boot selected
|
if (scancode == SC_ENTER) { // Boot selected
|
||||||
if (mbr.partitions[selected].type != 0) break;
|
if (mbr->partitions[selected].type != 0) break;
|
||||||
|
|
||||||
// Don't allow booting an unused partition
|
// Don't allow booting an unused partition
|
||||||
setAttr(0x4f);
|
setAttr(0x4f);
|
||||||
@@ -54,16 +76,11 @@ noreturn void main() {
|
|||||||
else if (selected == 4) selected = 0;
|
else if (selected == 4) selected = 0;
|
||||||
|
|
||||||
// Redraw
|
// Redraw
|
||||||
drawPartitions(&mbr, selected);
|
drawPartitions(mbr, selected);
|
||||||
partitonInfo(&mbr.partitions[selected]);
|
partitonInfo(&mbr->partitions[selected]);
|
||||||
}
|
}
|
||||||
|
|
||||||
setAttr(0x0f);
|
return &mbr->partitions[selected];
|
||||||
cls();
|
|
||||||
showCursor();
|
|
||||||
printf("Booting from Partition %d...", selected);
|
|
||||||
|
|
||||||
while (1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawPartitions(struct MBR* mbr, uint8_t sel) {
|
void drawPartitions(struct MBR* mbr, uint8_t sel) {
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#include "stdint.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "disk.h"
|
||||||
|
#include "fat32.h"
|
||||||
|
|
||||||
|
// Local context
|
||||||
|
struct fat32_ctx ctx;
|
||||||
|
|
||||||
|
int fat32_init(struct partition* p) {
|
||||||
|
readSectors(p->startLBA, 1, &ctx.bpb);
|
||||||
|
ctx.offsetBase = p->startLBA;
|
||||||
|
|
||||||
|
if (ctx.bpb.bytesPerSect != SECTOR_SIZE) return 1;
|
||||||
|
|
||||||
|
ctx.offsetFats = ctx.offsetBase + ctx.bpb.reservedSects;
|
||||||
|
ctx.offsetClusts = ctx.offsetFats + ctx.bpb.fatCount * ctx.bpb.sectsPerFat_32;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fat32_open(char* filename, int flags, ...) {
|
||||||
|
// TODO: flags
|
||||||
|
|
||||||
|
//struct fat32_traversed res = fat32_traverse(ctx, filename);
|
||||||
|
//if (!res.dir) return -1;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void fat32_close(void* file) {}
|
||||||
|
|
||||||
|
int fat32_read(const void* buf, size_t size, size_t count, void* file) {}
|
||||||
|
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
#ifndef _FAT32_H
|
||||||
|
#define _FAT32_H
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "defs.h"
|
||||||
|
#include "disk.h"
|
||||||
|
|
||||||
|
// Macros
|
||||||
|
#define FAT32_PTR(_p) ((struct fat32_ctx*)(_p))
|
||||||
|
#define FAT32_DIR_PTR(_p) ((struct fat32_fd*)(_p))
|
||||||
|
#define FAT32_FULL_CLUST(_hi, _lo) (((uint32_t)(_hi) << 16) | (_lo))
|
||||||
|
#define FAT32_INODE_GEN(_dir, _i) ((_dir) * 100 + (_i))
|
||||||
|
|
||||||
|
// Long File Name (LFN)
|
||||||
|
#define LFN_MAX 20
|
||||||
|
#define LFN_MAX_CHARS 256
|
||||||
|
|
||||||
|
// Attributes
|
||||||
|
#define FAT32_ATTR_READ_ONLY (1 << 0)
|
||||||
|
#define FAT32_ATTR_HIDDEN (1 << 1)
|
||||||
|
#define FAT32_ATTR_SYSTEM (1 << 2)
|
||||||
|
#define FAT32_ATTR_VOLUME_ID (1 << 3)
|
||||||
|
#define FAT32_ATTR_DIRECTORY (1 << 4)
|
||||||
|
#define FAT32_ATTR_ARCHIVE (1 << 5)
|
||||||
|
#define FAT32_ATTR_LFN \
|
||||||
|
(FAT32_ATTR_READ_ONLY | FAT32_ATTR_HIDDEN \
|
||||||
|
FAT32_ATTR_SYSTEM | FAT32_ATTR_VOLUME_ID)
|
||||||
|
|
||||||
|
/* On-disk structures */
|
||||||
|
|
||||||
|
// FAT32 Bios Parameter Block & Extended BPB
|
||||||
|
struct fat32_bpb {
|
||||||
|
uint8_t bootjmp[3];
|
||||||
|
char oemName[8];
|
||||||
|
uint16_t bytesPerSect;
|
||||||
|
uint8_t sectsPerClust;
|
||||||
|
uint16_t reservedSects;
|
||||||
|
uint8_t fatCount;
|
||||||
|
uint16_t rootEntryCount;
|
||||||
|
uint16_t totalSects_16;
|
||||||
|
uint8_t mediaType;
|
||||||
|
uint16_t sectsPerFat_16;
|
||||||
|
uint16_t sectsPerTrack;
|
||||||
|
uint16_t headCount;
|
||||||
|
uint32_t hiddenSects;
|
||||||
|
uint32_t sectCount_32;
|
||||||
|
// Extended
|
||||||
|
uint32_t sectsPerFat_32;
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t fatVersion;
|
||||||
|
uint32_t rootClust;
|
||||||
|
uint16_t fsinfoSect;
|
||||||
|
uint16_t backupBootsect;
|
||||||
|
uint8_t _reserved[12];
|
||||||
|
uint8_t driveNum;
|
||||||
|
uint8_t winNTFlags;
|
||||||
|
uint8_t signature;
|
||||||
|
uint32_t volumeID;
|
||||||
|
char volumeLabel[11];
|
||||||
|
char systemID[8];
|
||||||
|
uint8_t bootcode[420];
|
||||||
|
uint16_t bootsig;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
// FAT32 Directory Entry
|
||||||
|
struct fat32_dentry {
|
||||||
|
char name[8];
|
||||||
|
char ext[3];
|
||||||
|
uint8_t attr;
|
||||||
|
uint8_t userattr;
|
||||||
|
char undelete;
|
||||||
|
uint16_t createTime;
|
||||||
|
uint16_t createDate;
|
||||||
|
uint16_t accessDate;
|
||||||
|
uint16_t clustHigh;
|
||||||
|
uint16_t modifyTime;
|
||||||
|
uint16_t modifyDate;
|
||||||
|
uint16_t clustLow;
|
||||||
|
uint32_t size;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
// FAT32 Long File Name entry
|
||||||
|
struct fat32_lfn {
|
||||||
|
uint8_t order;
|
||||||
|
uint8_t name1[10];
|
||||||
|
uint8_t attr;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t checksum;
|
||||||
|
uint8_t name2[12];
|
||||||
|
uint16_t zero;
|
||||||
|
uint8_t name3[4];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* In memory structures */
|
||||||
|
struct fat32_ctx {
|
||||||
|
size_t offsetBase;
|
||||||
|
size_t offsetFats;
|
||||||
|
size_t offsetClusts;
|
||||||
|
|
||||||
|
struct fat32_bpb bpb;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fat32_fd {
|
||||||
|
uint32_t ptr;
|
||||||
|
uint8_t index;
|
||||||
|
uint32_t dirStart;
|
||||||
|
uint32_t dirCurrent;
|
||||||
|
struct fat32_dentry dentry;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
int fat32_init(struct partition* p);
|
||||||
|
int fat32_open(char* filename, int flags, ...); /* We won't use the va_args */
|
||||||
|
|
||||||
|
|
||||||
|
void* fat32_fopen(const char* path, const char* mode);
|
||||||
|
void fat32_fclose(void* file);
|
||||||
|
int fat32_fgetc(void* file);
|
||||||
|
char* fat32_fgets(char* s, size_t n, void* file);
|
||||||
|
int fat32_fread(const void* buf, size_t size, size_t count, void* file);
|
||||||
|
int fat32_fseek(void* file, size_t offset, int whence);
|
||||||
|
long fat32_ftell(void* file);
|
||||||
|
|
||||||
|
#endif
|
||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
int keyboardInit() { return 0; }
|
int keyboardInit() { return 0; }
|
||||||
|
|
||||||
uint8_t getScancode() {
|
uint8_t getScancode() {
|
||||||
while (inb(PS2_STAT_PORT) & 0x01 == 0);
|
while ((inb(PS2_STAT_PORT) & 0x01) == 0);
|
||||||
return inb(PS2_DATA_PORT);
|
return inb(PS2_DATA_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-6
@@ -8,9 +8,7 @@ static uint32_t xpos;
|
|||||||
static uint32_t ypos;
|
static uint32_t ypos;
|
||||||
static uint8_t attr;
|
static uint8_t attr;
|
||||||
|
|
||||||
void setAttr(uint8_t newattr) {
|
void setAttr(uint8_t newattr) { attr = newattr; }
|
||||||
attr = newattr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCursor(uint32_t row, uint32_t col) {
|
void setCursor(uint32_t row, uint32_t col) {
|
||||||
xpos = col;
|
xpos = col;
|
||||||
@@ -98,7 +96,6 @@ int vsnprintf(void* buf, size_t len, char* fmt, va_list args) {
|
|||||||
char pad = ' ';
|
char pad = ' ';
|
||||||
int width = 0;
|
int width = 0;
|
||||||
|
|
||||||
// TODO: padding
|
|
||||||
if (*fmt == '0') pad = '0';
|
if (*fmt == '0') pad = '0';
|
||||||
while (*fmt >= '0' && *fmt <= '9') {
|
while (*fmt >= '0' && *fmt <= '9') {
|
||||||
width *= 10;
|
width *= 10;
|
||||||
@@ -110,14 +107,19 @@ int vsnprintf(void* buf, size_t len, char* fmt, va_list args) {
|
|||||||
switch (*fmt++) {
|
switch (*fmt++) {
|
||||||
case 'd': s = itoa(va_arg(args, int), 10); goto string;
|
case 'd': s = itoa(va_arg(args, int), 10); goto string;
|
||||||
case 'x': s = itoa(va_arg(args, int), 16); goto string;
|
case 'x': s = itoa(va_arg(args, int), 16); goto string;
|
||||||
case 's': s = va_arg(args, char*);
|
case 's': s = va_arg(args, char*); goto string;
|
||||||
string: while (*s != '\0' && pos < len - 1) str[pos++] = *s++; break;
|
|
||||||
case 'c': if (pos < len - 1) str[pos++] = va_arg(args, char); break;
|
case 'c': if (pos < len - 1) str[pos++] = va_arg(args, char); break;
|
||||||
case '%': if (pos < len - 1) str[pos++] = '%'; break;
|
case '%': if (pos < len - 1) str[pos++] = '%'; break;
|
||||||
default:
|
default:
|
||||||
if (pos < len - 1) str[pos++] = '%';
|
if (pos < len - 1) str[pos++] = '%';
|
||||||
if (pos < len - 1) str[pos++] = *(fmt - 1);
|
if (pos < len - 1) str[pos++] = *(fmt - 1);
|
||||||
break;
|
break;
|
||||||
|
string:
|
||||||
|
width -= strlen(s) - 1;
|
||||||
|
if (width < 0) width = 0;
|
||||||
|
while (width-- && pos < len - 1) str[pos++] = pad;
|
||||||
|
while (*s && pos < len - 1) str[pos++] = *s++;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user