Skip to content

Commit ec73355

Browse files
Added MBR Support, FAT16 support and bug fixes.
1 parent 48117ac commit ec73355

14 files changed

Lines changed: 809 additions & 69 deletions

File tree

Makefile

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,21 @@ tarball:
5858
# QEMU targets
5959
# -----------------------------
6060
QEMU_COMMON = \
61-
-vga std \
62-
-debugcon stdio \
63-
-serial file:serial.log \
64-
-audiodev pa,id=speaker \
65-
-device rtl8139,netdev=eth0 \
66-
-netdev user,hostfwd=tcp::5555-:22,id=eth0 \
67-
-cdrom $(ISO_FILE) \
68-
-drive if=none,file=disk.txtimg,id=disk \
69-
-device ahci,id=ahci \
70-
-device ide-hd,drive=disk,bus=ahci.0 \
71-
-rtc base=localtime,clock=host \
72-
-m 512
61+
-vga std \
62+
-debugcon stdio \
63+
-serial file:serial.log \
64+
-boot menu=on \
65+
-audiodev pa,id=speaker \
66+
-device rtl8139,netdev=eth0 \
67+
-netdev user,hostfwd=tcp::5555-:22,id=eth0 \
68+
-device usb-ehci,id=ehci \
69+
-drive if=none,format=raw,file=$(ISO_FILE),id=usbdisk,index=0\
70+
-device usb-storage,drive=usbdisk \
71+
-drive if=none,format=raw,file=disk.txtimg,id=disk,index=1 \
72+
-device ahci,id=ahci \
73+
-device ide-hd,drive=disk,bus=ahci.0 \
74+
-rtc base=localtime,clock=host \
75+
-m 512
7376

7477
run-x86-hdd:
7578
@qemu-system-x86_64 $(QEMU_COMMON)

disk.txtimg

32 MB
Binary file not shown.

source/includes/ahci.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#define SECTOR_SIZE 512
2525

2626
#define ATA_CMD_WRITE_DMA_EXT 0x35
27+
#define ATA_CMD_IDENTIFY 0xEC
28+
2729

2830
/**
2931
* @brief AHCI device signatures.
@@ -130,6 +132,27 @@ typedef volatile struct {
130132
ahci_port_t ports[32]; /* array of port structures (0x100.. ) */
131133
} ahci_hba_mem_t;
132134

135+
typedef struct {
136+
uint64_t total_sectors;
137+
int present;
138+
} ahci_disk_info_t;
139+
140+
extern ahci_disk_info_t ahci_disks[32];
141+
142+
typedef struct {
143+
int disk;
144+
uint32_t lba_start;
145+
uint32_t sectors;
146+
uint8_t type;
147+
} block_part_t;
148+
149+
// For block devics
150+
typedef struct {
151+
int port;
152+
uint64_t sectors;
153+
154+
block_part_t partitions[4];
155+
} block_disk_t;
133156

134157
/**
135158
* @brief Global AHCI controller pointer.

source/includes/basics.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ typedef uint8_t int8;
2222
typedef const char* cstring;
2323
typedef char* string;
2424

25-
#define MiB *1024*1024
26-
#define KiB *1024
25+
#define GiB *1024*1024*1024ULL
26+
#define MiB *1024*1024ULL
27+
#define KiB *1024ULL
2728

2829
#define yes true
2930
#define no false

source/includes/commands/commands.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@ int cmd_fwfetch(int argc, char** argv);
3232
int cmd_help(int argc, char** argv);
3333
int cmd_lspci(int argc, char** argv);
3434
int cmd_clear(int argc, char** argv);
35+
int cmd_lsblk(int argc, char** argv);
3536

3637
#endif

source/includes/disk/gpt.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@
1111
#define GPT_PART_ATTRIB_USED_BY_OS 0b10
1212
#define GPT_ENTRIES_SIZE (512*31)/sizeof(GPT_PartitionEntry)
1313

14-
#if defined(__cplusplus)
15-
extern "C" {
16-
#endif
17-
1814
extern uint8_t GPT_EFI_SIGNATURE[]; // it's just "EFI PART"
1915

2016
struct GPT_PartTableHeader{
@@ -53,8 +49,4 @@ struct GPT_END{
5349
GPT_PartTableHeader PartitionTableHeaderMirror; // Has to be same as at the start
5450
} __attribute__((packed)) ;
5551

56-
#if defined(__cplusplus)
57-
} // extern "C"
58-
#endif
59-
6052
#endif

source/includes/disk/mbr.h

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,32 @@
1-
/*
1+
/**
2+
* @file mbr.h
3+
* @author Pradosh (pradoshgame@gmail.com)
4+
* @brief The header to read the LBA0 and check whether the disk is MBR.
5+
* @version 0.1
6+
* @date 2025-12-28
27
*
3-
* Master Boot Record (partition table)
8+
* @copyright Copyright (c) Pradosh 2025
49
*
510
*/
6-
#ifndef __MBR_H
7-
#define __MBR_H
8-
#include <stdint.h>
9-
#include <stddef.h>
11+
#ifndef MBR_H
12+
#define MBR_H
13+
#include <basics.h>
14+
#include <ahci.h>
1015

1116
#define MBR_PART_BOOTABLE 0x80
12-
#define MBR_VALID_MBR 0xaa55
1317

14-
#if defined( __cplusplus )
15-
extern "C" {
16-
#endif
18+
extern block_disk_t mbr_disks[10];
1719

18-
struct MBR_Partition{
19-
uint8_t Attributes;
20+
typedef struct {
21+
uint8_t boot_flag;
22+
uint8_t chs_start[3];
23+
uint8_t partition_type;
24+
uint8_t chs_end[3];
25+
uint32_t lba_start;
26+
uint32_t num_sectors;
27+
} __attribute__((packed)) mbr_partition_t;
2028

21-
uint8_t StartHead;
22-
uint8_t StartSector : 6;
23-
uint16_t StartCylinder : 10;
24-
25-
uint8_t SystemID;
26-
27-
uint8_t EndHead;
28-
uint8_t EndSector : 6;
29-
uint16_t EndCylinder : 10;
30-
31-
uint32_t LBA_Start;
32-
uint32_t SectorCount;
33-
} __attribute__((packed)) ;
34-
35-
struct MBR{
36-
uint8_t Bootloader[440];
37-
uint32_t UniqueDiskID;
38-
uint16_t Reserved0;
39-
MBR_Partition Partitions[4];
40-
uint16_t ValidationSignature;
41-
} __attribute__((packed)) ;
42-
43-
44-
#if defined( __cplusplus )
45-
}
46-
#endif
29+
void check_mbr(int portno);
30+
void parse_mbr_partitions(int8* mbr, int portno);
4731

4832
#endif
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* @file fat16.h
3+
* @author Pradosh (pradoshgame@gmail.com)
4+
* @brief The header file for reading in FAT16 file system
5+
* @version 0.1
6+
* @date 2025-12-28
7+
*
8+
* @copyright Copyright (c) Pradosh 2025
9+
*
10+
*/
11+
12+
#ifndef FAT16_H
13+
#define FAT16_H
14+
15+
#include <basics.h>
16+
#include <graphics.h>
17+
18+
typedef struct {
19+
uint8_t jmp[3];
20+
uint8_t oem[8];
21+
uint16_t bytes_per_sector;
22+
uint8_t sectors_per_cluster;
23+
uint16_t reserved_sectors;
24+
uint8_t num_fats;
25+
uint16_t max_root_dir_entries;
26+
uint16_t total_sectors_short; // if zero, use total_sectors_long
27+
uint8_t media_descriptor;
28+
uint16_t sectors_per_fat;
29+
uint16_t sectors_per_track;
30+
uint16_t num_heads;
31+
uint32_t hidden_sectors;
32+
uint32_t total_sectors_long;
33+
// We ignore the rest for now
34+
} __attribute__((packed)) fat16_boot_sector_t;
35+
36+
typedef struct {
37+
char name[8];
38+
char ext[3];
39+
uint8_t attr;
40+
uint8_t reserved;
41+
uint8_t creation_time_tenths;
42+
uint16_t creation_time;
43+
uint16_t creation_date;
44+
uint16_t last_access_date;
45+
uint16_t ignore; // high word of first cluster (FAT32 only)
46+
uint16_t last_mod_time;
47+
uint16_t last_mod_date;
48+
uint16_t first_cluster;
49+
uint32_t filesize;
50+
} __attribute__((packed)) fat16_dir_entry_t;
51+
52+
typedef struct {
53+
int portno;
54+
uint32_t partition_lba;
55+
56+
fat16_boot_sector_t bs;
57+
58+
uint32_t fat_start;
59+
uint32_t root_dir_start;
60+
uint32_t root_dir_sectors;
61+
uint32_t data_start;
62+
} fat16_fs_t;
63+
64+
typedef struct {
65+
fat16_fs_t* fs;
66+
fat16_dir_entry_t entry;
67+
uint32_t pos;
68+
uint16_t cluster;
69+
} fat16_file_t;
70+
71+
int detect_fat_type(int8* buf);
72+
int fat16_mount(int portno, uint32_t partition_lba, fat16_fs_t* fs) ;
73+
uint16_t fat16_read_fat_fs(fat16_fs_t* fs, uint16_t cluster);
74+
void fat16_list_root(fat16_fs_t* fs);
75+
int fat16_find_path(fat16_fs_t* fs, const char* path, fat16_dir_entry_t* out);
76+
int fat16_match_name(fat16_dir_entry_t* e, const char* name);
77+
int fat16_find_in_dir(fat16_fs_t* fs, uint16_t current_cluster, const char* name, fat16_dir_entry_t* out);
78+
void fat16_list_dir_cluster(fat16_fs_t* fs, uint16_t start_cluster);
79+
void fat16_format_name(const char* input, char out[11]);
80+
int fat16_find_file(fat16_fs_t* fs, const char* name, fat16_dir_entry_t* out);
81+
void fat16_read_file(fat16_fs_t* fs, fat16_dir_entry_t* file);
82+
int fat16_open(fat16_fs_t* fs, const char* path, fat16_file_t* f);
83+
int fat16_read(fat16_file_t* f, uint8_t* out, uint32_t size);
84+
int fat16_write(fat16_file_t* f, const uint8_t* data, uint32_t size);
85+
void fat16_close(fat16_file_t* f);
86+
87+
#endif

source/kernel/C/ahci.c

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <heap.h>
1313

1414
ahci_hba_mem_t* global_ahci_ctrl;
15+
ahci_disk_info_t ahci_disks[32];
1516

1617
void detect_ahci_devices(ahci_hba_mem_t* ahci_ctrl) {
1718
global_ahci_ctrl = ahci_ctrl;
@@ -33,6 +34,8 @@ void detect_ahci_devices(ahci_hba_mem_t* ahci_ctrl) {
3334

3435
uint32_t sig = port->sig;
3536

37+
printf("port->sig = 0x%x", port->sig);
38+
3639
switch (sig) {
3740
case sata_disk:
3841
printf("[AHCI] SATA Disk detected on port %d", i);
@@ -58,17 +61,28 @@ void detect_ahci_devices(ahci_hba_mem_t* ahci_ctrl) {
5861
void handle_sata_disk(int portno) {
5962
ahci_init_port(portno);
6063

61-
uint8_t* buf = kmalloc_aligned(512, 512);
62-
memset(buf, 0, 512);
64+
int16* id = kmalloc_aligned(512, 4096);
65+
66+
if (!id) {
67+
error("[AHCI] Allocation failed!", __FILE__);
68+
return;
69+
}
6370

64-
if (ahci_read_sector(portno, 0, buf, 1) != 0) {
65-
printf("[AHCI] Read LBA failed on port %d\n", portno);
71+
if (ahci_identify(portno, id) != 0) {
72+
printf("[AHCI] IDENTIFY failed on port %d", portno);
6673
return;
6774
}
6875

69-
for (int i = 0; i < 32; i++) printfnoln("%c", buf[i]);
76+
uint64_t sectors =
77+
((uint64_t)id[103] << 48) |
78+
((uint64_t)id[102] << 32) |
79+
((uint64_t)id[101] << 16) |
80+
((uint64_t)id[100]);
81+
82+
ahci_disks[portno].total_sectors = sectors;
83+
ahci_disks[portno].present = 1;
7084

71-
print("\n");
85+
check_mbr(portno);
7286

7387
// char* msg = "FROSTWING WAS HERE";
7488
// memset(buf, 0, 512);
@@ -77,13 +91,13 @@ void handle_sata_disk(int portno) {
7791
// uint64_t write_lba = 2; // or 10 for testing
7892

7993
// if (ahci_write_sector(portno, 0, buf, 1) != 0) {
80-
// printf("[AHCI] Write LBA failed\n");
94+
// printf("[AHCI] Write LBA failed");
8195
// return;
8296
// }
8397

8498
// memset(buf, 0, 512);
8599
// if (ahci_read_sector(portno, 0, buf, 1) != 0) {
86-
// printf("[AHCI] Read LBA failed\n");
100+
// printf("[AHCI] Read LBA failed");
87101
// return;
88102
// }
89103

@@ -240,3 +254,54 @@ int ahci_write_sector(int portno, uint64_t lba, void* buffer, uint32_t count) {
240254
port->is = 0xFFFFFFFF;
241255
return 0;
242256
}
257+
258+
int ahci_identify(int portno, void* buffer) {
259+
ahci_port_t* port = &global_ahci_ctrl->ports[portno];
260+
ahci_port_mem_t* mem = &port_mem[portno];
261+
262+
// Wait until port is ready
263+
while (port->tfd & (0x80 | 0x08)); // BSY | DRQ
264+
265+
int slot = ahci_find_slot(port);
266+
if (slot == -1) return -1;
267+
268+
ahci_cmd_header_t* hdr = &mem->cmd_list[slot];
269+
memset(hdr, 0, sizeof(*hdr));
270+
hdr->flags = 5;
271+
hdr->prdtl = 1; // one PRDT entry
272+
hdr->ctba = (uint32_t)(uintptr_t)mem->cmd_tables[slot];
273+
hdr->ctbau = 0;
274+
275+
276+
ahci_cmd_table_t* tbl = mem->cmd_tables[slot];
277+
memset(tbl->cfis, 0, 64);
278+
memset(tbl->prdt, 0, sizeof(tbl->prdt));
279+
280+
281+
tbl->prdt[0].dba = (uint32_t)(uintptr_t)buffer;
282+
tbl->prdt[0].dbau = 0;
283+
tbl->prdt[0].dbc = (512 - 1) | (1 << 31); // 512 bytes, IOC
284+
285+
uint8_t* cfis = tbl->cfis;
286+
cfis[0] = 0x27; // Host to device
287+
cfis[1] = 1 << 7; // Command
288+
cfis[2] = ATA_CMD_IDENTIFY; // IDENTIFY DEVICE
289+
cfis[7] = 0; // Features = 0
290+
cfis[8] = 0; cfis[9] = 0; cfis[10] = 0; // LBA = 0
291+
292+
port->serr = 0xFFFFFFFF;
293+
port->is = 0xFFFFFFFF;
294+
295+
port->ci = 1 << slot;
296+
297+
// Wait for completion
298+
while (port->ci & (1 << slot)) {
299+
if (port->tfd & (0x01 | 0x20)) { // ERR | DF
300+
port->is = 0xFFFFFFFF;
301+
return -2;
302+
}
303+
}
304+
305+
port->is = 0xFFFFFFFF;
306+
return 0;
307+
}

0 commit comments

Comments
 (0)