Skip to content

Commit b5649a2

Browse files
committed
Improve 32-bit disk driver to load upto 4GB anywhere within first 4GB of RAM
1 parent 34cbf7b commit b5649a2

File tree

12 files changed

+111
-32
lines changed

12 files changed

+111
-32
lines changed

emulator/Makefile.mk

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ QEMU_SHUT_FLAGS= -no-shutdown -no-reboot
22
QEMU_EXTRA_FLAGS=
33
QEMU_GDB_PORT=9000
44
QEMU_MONITOR_PORT=55555
5-
GDB_EX='echo Use GDB_EX="<command>" to execute command on connect.\n'
5+
GDB_EX=echo Use GDB_EX="<command>" to execute command on connect.\n
66

77
qemu: $(image_vmdk)
88
qemu-system-x86_64 -smp 1 -m 128M -hda $< $(QEMU_SHUT_FLAGS) $(QEMU_EXTRA_FLAGS)
@@ -17,6 +17,5 @@ qemu_debug: $(image_vmdk)
1717
qemu-system-x86_64 -S -gdb tcp::$(QEMU_GDB_PORT) -smp 1 -m 128M -hda $< $(QEMU_SHUT_FLAGS) -d cpu,exec,in_asm
1818

1919
qemu_debug_connect:
20-
gdb -x $(ROOT_DIR)/.gdbinit -ex "target remote :$(QEMU_GDB_PORT)" -ex "$(GDB_EX)" -ex 'continue'
21-
20+
gdb -x $(ROOT_DIR)/.gdbinit -ex "target remote :$(QEMU_GDB_PORT)" -ex '$(GDB_EX)' -ex 'continue'
2221

include/fuzzy/fs/ffs.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ int resolve_abs_lba(int parition_id, int partition_relative_lba);
5050

5151
int partition_read_block(int block_index, void *wr_buffer);
5252

53-
int fetch_first_block(
54-
union FFSMetaData *block);
53+
int verify_partition(int partition_id);
5554

5655
int fetch_file_entry(
5756
int partition_id,

include/fuzzy/memmgr/layout.asm

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
; constants only
22

33
; START_ENSURE_SAME_layout_h
4-
MEMORY_APP_SIZE EQU 0x20000
5-
4+
MEMORY_APP_SIZE EQU 0x20000
65
; END_ENSURE_SAME_layout_h
76

87
; Kernel core is app with pid 0

include/fuzzy/memmgr/layout.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
// START_ENSURE_SAME_layout_asm
44
#define MEMORY_APP_SIZE 0x20000
55
#define STACKINIT_APP (MEMORY_APP_SIZE-4)
6+
#define MEMORY_REALLIBRARY_DATA_ADDRESS 0x70000
7+
#define MEMORY_REALLIBRARY_DATA_SIZE 0x10000
8+
69
// END_ENSURE_SAME_layout_asm
710

811
// Most of the memory layout relies on the fact the kernel is first app

include/fuzzy/memmgr/tables/gdt.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ struct GDTEntry {
3030
};
3131
#pragma pack(pop)
3232

33-
#define GDT_KERNEL_CS (GDT_STD_SELECTOR_KERNEL_CS*sizeof(struct GDTEntry))
33+
#define GDT_NULL_CS (GDT_STD_SELECTOR_NULL*sizeof(struct GDTEntry))
34+
#define GDT_KERNEL_CS (GDT_STD_SELECTOR_KERNEL_CS*sizeof(struct GDTEntry))
35+
#define GDT_KERNEL_DS (GDT_STD_SELECTOR_KERNEL_DS*sizeof(struct GDTEntry))
36+
#define GDT_ABS16_CS (GDT_STD_SELECTOR_ABS16_CS*sizeof(struct GDTEntry))
37+
#define GDT_ABS16_DS (GDT_STD_SELECTOR_ABS16_DS*sizeof(struct GDTEntry))
38+
#define GDT_ABS32_DS (GDT_STD_SELECTOR_ABS32_DS*sizeof(struct GDTEntry))
3439

3540
int get_gdt_baseaddress(struct GDTEntry gdt_table[], unsigned int table_size, int entry_id);
3641

memory_layout.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
| From | To | Size | Usage |
44
|--------- |-------- |-------- |-------------------------------------------- |
55
| 0x00000 | 0x003FF | - | IVT (standard) |
6-
| 0x00400 | 0x07BFF | - | BIOS data area + reserv |
6+
| 0x00400 | 0x07BFF | - | BIOS data area + reserve |
77
| 0x07C00 | 0x07DFF | 512B | Bootloader Stage 1 |
88
| 0x07E00 | 0x07FFF | 512B | STATIC CODE for real_mode library |
99
| 0x08000 | 0x0BFFF | - | Bootloader Stage 2 + own stack |
1010
| 0x0F000 | 0x2EFFF | 128KB | Kernel + (core, irq, syscall) stack |
1111
| 0x30000 | 0x4FFFF | 128KB | App pid 1 |
1212
| 0x50000 | 0x6FFFF | 128KB | App pid 2 |
13-
| 0x70000 | - | - | - |
13+
| 0x70000 | 0x7FFFF | 64KB | Extra space for real_mode library+client |
1414
| 0x80000 | 0x9FFFF | 128KB | Extended BIOS Data area |
1515
| 0xA0000 | 0xBFFFF | 128KB | Video memory |
1616
| 0xC0000 | 0xFFFFF | 256KB | BIOS stuff |

src/drivers/disk/disk.c

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
// written for protected mode
22
#include <fuzzy/kernel/process/process.h>
3+
#include <fuzzy/memmgr/tables/gdt.h>
4+
#include <fuzzy/memmgr/layout.h>
35

46
#include <lib/utils/logging.h>
57
#include <fuzzy/real_mode/client.h>
68

7-
int load_sectors(unsigned int full_address,
8-
unsigned char drive,
9-
unsigned int lba, // 0-based
10-
unsigned char count) {
11-
int es = (full_address&0xF0000)>>4;
12-
int es_address = full_address&0xFFFF;
9+
#define SECTOR_SIZE 512
10+
11+
static int load_sector_via_reallibrary_data(
12+
unsigned int dst_address,
13+
unsigned char drive,
14+
unsigned int lba,
15+
unsigned char count) {
16+
// assumes count <= 128
17+
int es = (MEMORY_REALLIBRARY_DATA_ADDRESS&0xF0000)>>4;
18+
int es_address = MEMORY_REALLIBRARY_DATA_ADDRESS&0xFFFF;
1319
int cylinder_head = (lba/63);
1420
int sector_index = lba%63 + 1;
1521
// https://en.wikipedia.org/wiki/INT_13H#INT_13h_AH=02h:_Read_Sectors_From_Drive
@@ -28,13 +34,46 @@ int load_sectors(unsigned int full_address,
2834
drive,
2935
0
3036
);
31-
unsigned int status = eax >> 8;
32-
print_info("[load_sectors] [dev %x]:%x -> mem:%x, cnt: %d; err: %x",
33-
drive, lba, full_address, count, status);
34-
if(status == 0) {
35-
// no error copy from temporary address to dst address.
36-
// TODO: redefine GDT table order.
37-
// kernel_memncpy_absolute(int dst_ds, char *dst_address, int src_ds, char *src_address, size_t size);
37+
unsigned int err = eax >> 8;
38+
if(err) return err;
39+
40+
// copy from temporary memory to real dst address.
41+
int dst_ds = GDT_ABS32_DS;
42+
int src_ds = GDT_ABS32_DS;
43+
44+
kernel_memncpy_absolute(
45+
dst_ds,
46+
dst_address,
47+
src_ds,
48+
MEMORY_REALLIBRARY_DATA_ADDRESS,
49+
SECTOR_SIZE*(int)count);
50+
print_info("[load_sectors] mem %x:%x -> mem %x:%x, cnt: %d; err: %d",
51+
src_ds, MEMORY_REALLIBRARY_DATA_ADDRESS, dst_ds, dst_address, SECTOR_SIZE*(int)count, 0);
52+
53+
return 0;
54+
};
55+
56+
int load_sectors(unsigned int dst_address,
57+
unsigned char drive,
58+
unsigned int lba, // 0-based
59+
unsigned int sector_count) {
60+
// load_sector_via_reallibrary_data supports upto 255 sector count
61+
// but the memory allocation for reallibrary data is 0x10000 which
62+
// amounts to 128 sectors. Please have a look at memory_layout.md
63+
const int OCC_MAX_SECTOR_COUNT = 128;
64+
65+
int err = 0;
66+
while(!err && sector_count>0) {
67+
int occ_read_sectors = min(sector_count, OCC_MAX_SECTOR_COUNT);
68+
err = load_sector_via_reallibrary_data(
69+
dst_address,
70+
drive,
71+
lba,
72+
occ_read_sectors
73+
);
74+
dst_address += SECTOR_SIZE*occ_read_sectors;
75+
lba += occ_read_sectors;
76+
sector_count -= occ_read_sectors;
3877
}
39-
return status;
78+
return err;
4079
}

src/drivers/disk/disk.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
int load_sectors(unsigned int full_address,
44
unsigned char drive,
55
unsigned int lba, // 0-based
6-
unsigned char count);
6+
unsigned int count);

src/drivers/disk/disk_16.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ extern unsigned short _low_int_0x13(unsigned short ax,
99
int load_sectors(unsigned int full_address,
1010
unsigned char drive,
1111
unsigned int lba, // 0-based
12-
unsigned char count) {
12+
unsigned int count) {
13+
// we don't expect disk_16 (used by bootloader) to load more than 255 sectors.
14+
1315
int es = (full_address&0xF0000)>>4;
1416
int es_address = full_address&0xFFFF;
1517
int cylinder_head = (lba/63);

src/fs/ffs.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,34 @@ int partition_read_block(int lba, void *wr_buffer) {
1414
return err;
1515
}
1616

17-
int fetch_first_block(
18-
union FFSMetaData *block) {
19-
return partition_read_block(0, block->bytes);
17+
int verify_partition(int partition_id) {
18+
// cache
19+
// -1: not yet verified
20+
// 0: verified with no error
21+
// 1: verified but failed
22+
static char verified_cache[4] = {-1, -1, -1, -1};
23+
if(partition_id<0 || partition_id>=4) return 1;
24+
if(verified_cache[partition_id]!=-1) return verified_cache[partition_id];
25+
26+
// fetch parition info
27+
struct PartitionEntry partition;
28+
read_partition_entry(partition_id, &partition);
29+
30+
union FFSMetaData block;
31+
int err = partition_read_block(
32+
partition.lba, // FS metadata
33+
block.bytes);
34+
if (!err) {
35+
// verify signature
36+
err = strcmp(block.content.signature, FS_FFS_SIGNATURE);
37+
}
38+
if (err) {
39+
verified_cache[partition_id] = 1; // err
40+
print_log("[ffs] partition %d verification failed, err: %d", partition_id, err);
41+
return err;
42+
}
43+
verified_cache[partition_id] = 0; // no error
44+
return 0;
2045
}
2146

2247
int resolve_abs_lba(int partition_id, int partition_relative_lba) {
@@ -30,14 +55,19 @@ int fetch_file_entry(
3055
int partition_id,
3156
int entry_id,
3257
union FFSFileEntry *entry) {
58+
int err = verify_partition(partition_id);
59+
if (err) {
60+
return err;
61+
}
62+
3363
char buffer[FS_BLOCK_SIZE];
3464
// fetch parition info
3565
struct PartitionEntry partition;
3666
read_partition_entry(partition_id, &partition);
3767

3868
// fetch file entry
3969
const int FILE_ENTRY_PER_BLOCK = (FS_BLOCK_SIZE/FS_FFS_FILEENTRY_SIZE);
40-
int err = partition_read_block(
70+
err = partition_read_block(
4171
partition.lba +
4272
1 + // FS metadata
4373
entry_id/FILE_ENTRY_PER_BLOCK,

0 commit comments

Comments
 (0)