Preliminary support for CHS disks.
This commit is contained in:
parent
d1f1bfa974
commit
6a4c1908bb
2
bochsrc
2
bochsrc
@ -11,7 +11,7 @@ floppy_bootsig_check: disabled=0
|
||||
floppya: type=none
|
||||
# no floppyb
|
||||
ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
|
||||
ata0-master: type=disk, path="virtdisk.bin", mode=flat, cylinders=2, heads=16, spt=63, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto
|
||||
ata0-master: type=disk, path="virtdisk.bin", mode=flat, cylinders=8, heads=16, spt=63, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto
|
||||
ata0-slave: type=none
|
||||
ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15
|
||||
ata1-master: type=none
|
||||
|
117
boot.nasm
117
boot.nasm
@ -23,14 +23,14 @@ add word [addr_packet_transfer_buff_seg], (secreadcnt*512)/16
|
||||
add word [addr_packet_start_block], secreadcnt
|
||||
loop read_loop
|
||||
entry:
|
||||
mov ax,0x2403 ; A20 BIOS Support
|
||||
int 0x15
|
||||
jb .no_a20
|
||||
cmp ah,0
|
||||
jnz .no_a20
|
||||
mov ax,0x2401 ; A20 BIOS Activate
|
||||
int 0x15
|
||||
.no_a20:
|
||||
;mov ax,0x2403 ; A20 BIOS Support
|
||||
;int 0x15
|
||||
;jb .no_a20
|
||||
;cmp ah,0
|
||||
;jnz .no_a20
|
||||
;mov ax,0x2401 ; A20 BIOS Activate
|
||||
;int 0x15
|
||||
;.no_a20:
|
||||
cli ; no interrupts
|
||||
xor ax,ax
|
||||
mov ds, ax
|
||||
@ -39,15 +39,41 @@ mov eax, cr0 ; set pmode bit
|
||||
or al, 1
|
||||
mov cr0, eax
|
||||
jmp 08h:Pmode
|
||||
no_exten:
|
||||
; read with CHS
|
||||
; FIXME This only reads up to sector count
|
||||
mov ah,8
|
||||
int 0x13 ; geometry
|
||||
and cx, 0x3f
|
||||
push cx
|
||||
push 0x0080 ; DH=head,DL=disk
|
||||
push 0x2000 ; buffer seg
|
||||
push 2 ; sector
|
||||
.loop:
|
||||
mov ax, [esp]
|
||||
push 0xb800
|
||||
pop es
|
||||
xor di,di
|
||||
call hexprint
|
||||
mov ax, [esp+2]
|
||||
mov es, ax
|
||||
mov ax, 0x0201
|
||||
mov cx, [esp]
|
||||
xor bx,bx
|
||||
mov dx, [esp+4]
|
||||
int 0x13
|
||||
jc err
|
||||
add word [esp+2], 0x20
|
||||
mov cx, [esp]
|
||||
inc cl
|
||||
mov [esp], cx
|
||||
cmp cl, [esp+6]
|
||||
jg entry
|
||||
jmp .loop
|
||||
err:
|
||||
mov bx, ax
|
||||
mov si, string
|
||||
mov cx, string_end - string
|
||||
jmp print
|
||||
no_exten:
|
||||
mov bx, ax
|
||||
mov si, no_exten_str
|
||||
mov cx, no_exten_str_end - no_exten_str
|
||||
print:
|
||||
push 0xb800
|
||||
pop es
|
||||
@ -57,9 +83,9 @@ err_print:
|
||||
lodsb
|
||||
stosw
|
||||
loop err_print
|
||||
add di, 2
|
||||
mov ax, bx
|
||||
call hexprint
|
||||
;add di, 2
|
||||
;mov ax, bx
|
||||
;call hexprint
|
||||
hlt_loop:
|
||||
hlt
|
||||
jmp hlt_loop
|
||||
@ -100,20 +126,57 @@ mov [esi], esi
|
||||
mov [edi], edi
|
||||
cmpsd
|
||||
jne .kernel
|
||||
in al, 0x92 ; fast A20
|
||||
test al, 2
|
||||
jnz .fa20_end
|
||||
or al, 2
|
||||
and al, 0xFE
|
||||
out 0x92, al
|
||||
.fa20_end:
|
||||
call enable_A20
|
||||
;in al, 0x92 ; fast A20
|
||||
;test al, 2
|
||||
;jnz .fa20_end
|
||||
;or al, 2
|
||||
;and al, 0xFE
|
||||
;out 0x92, al
|
||||
;.fa20_end:
|
||||
jmp .a20
|
||||
.kernel:
|
||||
mov esi, 0x8000
|
||||
;mov dword [0xb8000], 0x07000700 | 'P' | 'M' << 16
|
||||
;mov dword [0xb8004], 0x07000700 | 'O' | 'D' << 16
|
||||
;mov dword [0xb8008], 0x07000700 | 'E' | ' ' << 16
|
||||
mov esi, 0x20000
|
||||
mov edi, 0x100000
|
||||
mov ecx, 0x10000
|
||||
rep movsb
|
||||
jmp 08h:0x100000
|
||||
enable_A20:
|
||||
cli
|
||||
call a20wait
|
||||
mov al,0xAD
|
||||
out 0x64,al
|
||||
call a20wait
|
||||
mov al,0xD0
|
||||
out 0x64,al
|
||||
call a20wait2
|
||||
in al,0x60
|
||||
push eax
|
||||
call a20wait
|
||||
mov al,0xD1
|
||||
out 0x64,al
|
||||
call a20wait
|
||||
pop eax
|
||||
or al,2
|
||||
out 0x60,al
|
||||
call a20wait
|
||||
mov al,0xAE
|
||||
out 0x64,al
|
||||
call a20wait
|
||||
ret
|
||||
a20wait:
|
||||
in al,0x64
|
||||
test al,2
|
||||
jnz a20wait
|
||||
ret
|
||||
a20wait2:
|
||||
in al,0x64
|
||||
test al,1
|
||||
jz a20wait2
|
||||
ret
|
||||
|
||||
gdt_desc:
|
||||
dw gdt_end - gdt
|
||||
@ -134,12 +197,12 @@ gdt_end:
|
||||
|
||||
string: db 'DISK ERROR'
|
||||
string_end:
|
||||
no_exten_str: db 'NO INT13 EXTEN'
|
||||
no_exten_str_end:
|
||||
;no_exten_str: db 'NO INT13 EXTEN'
|
||||
;no_exten_str_end:
|
||||
|
||||
addr_packet:
|
||||
db 0x10, 0x00 ; size, reserved
|
||||
dw secreadcnt ; blocks
|
||||
addr_packet_transfer_buff_off: dw 0x0000 ; transfer buffer offset
|
||||
addr_packet_transfer_buff_seg: dw 0x0800 ; transfer buffer segment
|
||||
addr_packet_transfer_buff_seg: dw 0x2000 ; transfer buffer segment
|
||||
addr_packet_start_block: dq 1 ; start block
|
||||
|
@ -11,7 +11,17 @@
|
||||
#include "dosfs.h"
|
||||
#include "tmpstring.c"
|
||||
#include "../v86defs.h"
|
||||
#include "../print.h"
|
||||
|
||||
extern uint32_t _gpf_eax_save;
|
||||
extern uint32_t _gpf_eflags_save;
|
||||
extern uint16_t error_screen[80*50]; // defined in kernel.c
|
||||
__attribute((__no_caller_saved_registers__))
|
||||
extern void error_environment(); // defined in kernel.c
|
||||
uint32_t numHead;
|
||||
uint32_t secPerTrack;
|
||||
uint32_t maxCylinder;
|
||||
char useCHS = -1;
|
||||
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
|
||||
// NOTE If the buffer provided is outside the 0x20000-0x2FE00 range,
|
||||
// the function will use that buffer for the Virtual 8086 process
|
||||
@ -19,6 +29,38 @@ uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t
|
||||
uint8_t *v86buf = buffer;
|
||||
if ((uintptr_t)v86buf < 0x20000 || (uintptr_t)v86buf > 0x2FE00)
|
||||
v86buf = (uint8_t *)0x20000;
|
||||
|
||||
// TODO This check should probably happen at the kernel level
|
||||
if (useCHS == -1) {
|
||||
union V86Regs_t regs;
|
||||
// Check for INT 13 Extensions support
|
||||
regs.h.ah = 0x41;
|
||||
regs.w.bx = 0x55AA;
|
||||
regs.h.dl = 0x80;
|
||||
V8086Int(0x13, ®s);
|
||||
// LBA supported if CF clear
|
||||
if (!(_gpf_eflags_save & 0x1)) {
|
||||
useCHS = 0;
|
||||
} else {
|
||||
FARPTR v86_entry = i386LinearToFp(v86DiskGetGeometry);
|
||||
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||
// check CF for error
|
||||
if (_gpf_eflags_save & 0x1) {
|
||||
uint16_t *vga = error_screen;
|
||||
vga += printStr("Could not get Disk Geometry.", vga);
|
||||
error_environment();
|
||||
for(;;);
|
||||
}
|
||||
numHead = ((_gpf_eax_save & 0xff00) >> 8) + 1;
|
||||
secPerTrack = _gpf_eax_save & 0x3f;
|
||||
maxCylinder = ((_gpf_eax_save & 0xff0000) >> 16) | ((_gpf_eax_save & 0xc0) << 2);
|
||||
useCHS = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Do error handling
|
||||
if (!useCHS) {
|
||||
// LBA Read
|
||||
v86disk_addr_packet.start_block = sector;
|
||||
v86disk_addr_packet.blocks = count;
|
||||
v86disk_addr_packet.transfer_buffer =
|
||||
@ -27,6 +69,21 @@ uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t
|
||||
union V86Regs_t regs;
|
||||
FARPTR v86_entry = i386LinearToFp(v86DiskRead);
|
||||
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||
} else {
|
||||
uint32_t tmp = sector / secPerTrack;
|
||||
uint32_t sec = (sector % (secPerTrack)) + 1;
|
||||
uint32_t head = tmp % numHead;
|
||||
uint32_t cyl = tmp / numHead;
|
||||
union V86Regs_t regs;
|
||||
regs.w.ax = 0x0201;
|
||||
regs.h.ch = cyl & 0xff;
|
||||
regs.h.cl = sec | ((cyl >> 2) & 0xc0);
|
||||
regs.h.dh = head;
|
||||
regs.h.dl = 0x80;
|
||||
regs.w.bx = (uintptr_t)v86buf & 0xFFFF;
|
||||
FARPTR v86_entry = i386LinearToFp(v86DiskReadCHS);
|
||||
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||
}
|
||||
if (v86buf != buffer)
|
||||
memcpy(buffer, v86buf, count * SECTOR_SIZE);
|
||||
return 0;
|
||||
|
13
entry.nasm
13
entry.nasm
@ -1,5 +1,8 @@
|
||||
global entry
|
||||
entry:
|
||||
mov dword [0xb8000], 0x07000700 | 'E' | 'N' << 16
|
||||
mov dword [0xb8004], 0x07000700 | 'T' | 'R' << 16
|
||||
mov dword [0xb8008], 0x07000700 | 'Y' | ' ' << 16
|
||||
lgdt [gdt_desc] ; load gdt register
|
||||
jmp 08h:Pmodecode
|
||||
|
||||
@ -19,9 +22,19 @@ mov eax, 0x1f001f00
|
||||
mov ecx, (80*25)/2
|
||||
mov edi, 0xb8000
|
||||
rep stosd ; clear screen
|
||||
mov eax, dword [kernel_check]
|
||||
cmp eax, 0x12345678
|
||||
jne err
|
||||
call start
|
||||
hlt_loop:
|
||||
hlt
|
||||
jmp hlt_loop
|
||||
err:
|
||||
mov dword [0xb8000], 0x07000700 | 'L' | 'O' << 16
|
||||
mov dword [0xb8004], 0x07000700 | 'A' | 'D' << 16
|
||||
mov dword [0xb8008], 0x07000700 | 'F' | 'A' << 16
|
||||
mov dword [0xb800C], 0x07000700 | 'I' | 'L' << 16
|
||||
jmp hlt_loop
|
||||
|
||||
extern start
|
||||
extern kernel_check
|
||||
|
@ -24,6 +24,8 @@ jmp .hlt
|
||||
|
||||
global _gpf_eax_save
|
||||
_gpf_eax_save: dd 0
|
||||
global _gpf_eflags_save
|
||||
_gpf_eflags_save: dd 0
|
||||
extern gpf_handler_v86
|
||||
global gpfHandler
|
||||
gpfHandler:
|
||||
@ -52,6 +54,7 @@ pop ecx
|
||||
pop ebx
|
||||
sti ; we shouldn't crash now?
|
||||
mov eax, dword [esp+16] ; EFLAGS
|
||||
mov dword [_gpf_eflags_save], eax ; save
|
||||
and eax, 1 << 17 ; VM flag
|
||||
test eax, eax
|
||||
pop eax
|
||||
|
1
kernel.c
1
kernel.c
@ -297,6 +297,7 @@ void FileSelect() {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t kernel_check= 0x12345678;
|
||||
void start() {
|
||||
word *vga_text = (word *)0xb8000;
|
||||
char h[] = "LuciaOS";
|
||||
|
4
link.ld
4
link.ld
@ -4,11 +4,11 @@ ENTRY(entry)
|
||||
SECTIONS {
|
||||
. = 0x100000;
|
||||
|
||||
.text : ALIGN(0x1000) {
|
||||
.text : {
|
||||
*(.text);
|
||||
}
|
||||
|
||||
.data : ALIGN(0x1000) {
|
||||
.data : {
|
||||
*(.data);
|
||||
*(.rodata);
|
||||
*(.rodata*);
|
||||
|
70
tests.c
70
tests.c
@ -34,23 +34,74 @@ char TestUser() {
|
||||
return 0;
|
||||
}
|
||||
void TestDiskRead() {
|
||||
//vga_text += printStr("Starting Disk Read... ", vga_text);
|
||||
union V86Regs_t regs;
|
||||
uint16_t *vga_text = (uint16_t *)0xb8000 + (80*5);
|
||||
vga_text += printStr("Setting Text Mode... ", vga_text);
|
||||
regs.w.ax = 3; // text mode
|
||||
V8086Int(0x10, ®s);
|
||||
//vga_text += printStr("Done. Starting Disk Read... ", vga_text);
|
||||
char *diskReadBuf = (char *)0x20000;
|
||||
v86disk_addr_packet.transfer_buffer =
|
||||
(uintptr_t)diskReadBuf & 0x000F |
|
||||
(((uintptr_t)diskReadBuf & 0xFFFF0) << 12);
|
||||
FARPTR v86_entry = i386LinearToFp(v86DiskRead);
|
||||
enter_v86(0x0000, 0x8000, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||
vga_text = (uint16_t *)0xb8000;
|
||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||
for (int i = 0; i < (80*25)/2; i++) {
|
||||
printByte(diskReadBuf[i], &vga_text[i*2]);
|
||||
}
|
||||
}
|
||||
extern uint32_t _gpf_eax_save;
|
||||
extern uint32_t _gpf_eflags_save;
|
||||
void TestCHS() {
|
||||
uint16_t *vga_text = (uint16_t*)0xb8000;
|
||||
printStr("CHS Test ", vga_text);
|
||||
// CHS Read
|
||||
union V86Regs_t regs;
|
||||
FARPTR v86_entry = i386LinearToFp(v86DiskGetGeometry);
|
||||
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||
// check CF for error
|
||||
if (_gpf_eflags_save & 0x1) {
|
||||
uint16_t *vga = &((uint16_t*)0xb8000)[80];
|
||||
vga += printStr("Could not get Disk Geometry.", vga);
|
||||
return;
|
||||
}
|
||||
uint32_t numHead = ((_gpf_eax_save & 0xff00) >> 8) + 1;
|
||||
uint32_t secPerTrack = _gpf_eax_save & 0x3f;
|
||||
uint32_t maxCyl = ((_gpf_eax_save & 0xff0000) >> 16) | ((_gpf_eax_save & 0xc0) << 2);
|
||||
uint32_t maxLBA = numHead * secPerTrack * (maxCyl + 1);
|
||||
for (uint32_t sector = 0; sector < maxLBA && sector < 0x8000 /* don't bother reading huge disks */; sector += (sector + secPerTrack < maxLBA) ? secPerTrack : 1) {
|
||||
uint16_t *vga = &((uint16_t*)0xb8000)[9];
|
||||
vga += printWord(sector, vga); vga++;
|
||||
// LBA -> CHS
|
||||
uint32_t tmp = sector / secPerTrack;
|
||||
uint32_t sec = (sector % (secPerTrack)) + 1;
|
||||
uint32_t head = tmp % numHead;
|
||||
uint32_t cyl = tmp / numHead;
|
||||
vga += printWord(cyl, vga); vga += printChar(':', vga);
|
||||
vga += printByte(head, vga); vga += printChar(':', vga);
|
||||
vga += printByte(sec, vga); vga += printChar(' ', vga);
|
||||
vga += printStr("/ ", vga);
|
||||
vga += printWord(maxCyl, vga); vga += printChar(':', vga);
|
||||
vga += printByte(numHead - 1, vga); vga += printChar(':', vga);
|
||||
vga += printByte(secPerTrack, vga); vga += printChar(' ', vga);
|
||||
regs.w.ax = 0x0201;
|
||||
regs.h.ch = cyl & 0xff;
|
||||
regs.h.cl = sec | ((cyl >> 2) & 0xc0);
|
||||
regs.h.dh = head;
|
||||
regs.h.dl = 0x80;
|
||||
regs.w.bx = 0x0000;
|
||||
v86_entry = i386LinearToFp(v86DiskReadCHS);
|
||||
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||
// if CF was set, we have error
|
||||
if (_gpf_eflags_save & 0x1) {
|
||||
uint16_t *vga = &((uint16_t*)0xb8000)[80];
|
||||
vga += printStr("Disk Error: ", vga);
|
||||
vga += printByte(_gpf_eax_save & 0xff, vga);
|
||||
vga += printStr(" CHS=", vga);
|
||||
vga += printWord(cyl, vga); vga += printChar(':', vga);
|
||||
vga += printByte(head, vga); vga += printChar(':', vga);
|
||||
vga += printByte(sec, vga);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void TestFAT() {
|
||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||
uint8_t *diskReadBuf = (uint8_t *)0x22400;
|
||||
@ -144,6 +195,13 @@ void RunTests() {
|
||||
vga_text += printStr("Usermode test failed! Press any key to continue.", vga_text);
|
||||
}
|
||||
kbd_wait();
|
||||
union V86Regs_t regs;
|
||||
vga_text = (uint16_t *)0xb8000 + (80*5);
|
||||
vga_text += printStr("Setting Text Mode... ", vga_text);
|
||||
regs.w.ax = 3; // text mode
|
||||
V8086Int(0x10, ®s);
|
||||
TestCHS();
|
||||
kbd_wait();
|
||||
TestDiskRead();
|
||||
kbd_wait();
|
||||
TestFAT();
|
||||
|
20
v86.nasm
20
v86.nasm
@ -108,3 +108,23 @@ db 0x10, 0x00 ; size, reserved
|
||||
dw 0x1 ; blocks
|
||||
dd 0x23000000 ; transfer buffer 0x23000
|
||||
dq 0x1 ; start block
|
||||
|
||||
global v86DiskGetGeometry
|
||||
v86DiskGetGeometry:
|
||||
mov ah, 8
|
||||
mov dl, 0x80
|
||||
int 0x13
|
||||
movzx eax, ch
|
||||
shl eax, 16
|
||||
mov al, cl
|
||||
mov ah, dh
|
||||
int 0x30
|
||||
ud2
|
||||
|
||||
global v86DiskReadCHS
|
||||
v86DiskReadCHS:
|
||||
push 0x2000
|
||||
pop es
|
||||
int 0x13
|
||||
int 0x30
|
||||
ud2
|
||||
|
Loading…
Reference in New Issue
Block a user