Page 1 of 1
[SOLVED] How to read large portion of the floppy with BIOS ?
Posted: Fri Nov 01, 2013 4:27 pm
by wichtounet
Hi,
As all of you, I've been drawn to develop my own operating system and I'm having a lot of fun
But I've a problem with the loading from the floppy that I was unable to solve. My kernel is loaded from the floppy using the int 0x13 call.
Here is the code I'm using to load the kernel into memory in my bootloader:
Code: Select all
xor ax, ax
xor ah, ah
mov dl, 0
int 0x13
jc reset_failed
KERNEL_BASE equ 0x100 ; 0x0100:0x0 = 0x1000
sectors equ 0x30 ; sectors to read
mov ax, KERNEL_BASE
mov es, ax
xor bx, bx
mov ah, 0x2 ; Read sectors from memory
mov al, sectors ; Number of sectors to read
xor ch, ch ; Cylinder 0
mov cl, 2 ; Sector 2
xor dh, dh ; Head 0
mov dl, 0 ; Drive
int 0x13
jc read_failed
cmp al, sectors
jne read_failed
jmp dword KERNEL_BASE:0x0
This code works with 0x30 sectors, but now my kernel is growing larger and I need more sectors. But, when I replace the sectors line with:
Code: Select all
sectors equ 0x40 ; sectors to read
it doesn't work anymore.
Bochs logs these two lines:
00076015894i[CPU0 ] LOCK prefix unallowed (op1=0x53, modrm=0x00)
00076015898i[CPU0 ] LOCK prefix unallowed (op1=0x53, modrm=0x00)
And nothing else happens. The data on the floppy remains exactly the same and there is no LOCK prefix in it.
I suppose that's because I'm trying to read too many sectors at once and it just fails at some point. So, what is a good method to read many sectors from the floppy ? Do I have to read sectors one by one using something like a lba to chs function ?
Thank you
Re: How to read large portion of the floppy with BIOS ?
Posted: Fri Nov 01, 2013 4:38 pm
by Nable
Sometimes it's better to use loop instead of one large call (especially when you're in real mode, it's very easy to overwrite smth due to segment wrap-around/overrun).
Btw, your error seems to look like some buffer overflow when code is overwritten with data.
Upd: just look, if your bootloader is at 0x7C00, then you cannot load more than 0x6C00 bytes (0x36 sectors) to 0x1000. Btw, where did you place your stack?
Re: How to read large portion of the floppy with BIOS ?
Posted: Sat Nov 02, 2013 1:10 am
by egos
wichtounet, read floppy sector-by-sector or track-by-track (don't overrun 64-kb boundaries in memory space).
Re: How to read large portion of the floppy with BIOS ?
Posted: Sat Nov 02, 2013 2:43 am
by wichtounet
Nable wrote:Upd: just look, if your bootloader is at 0x7C00, then you cannot load more than 0x6C00 bytes (0x36 sectors) to 0x1000. Btw, where did you place your stack?
Oh god
I feel stupid now. I'll load the code in another memory location.
Nable wrote:Btw, where did you place your stack?
I already checked the stack, it it before 0x1000, but I forgot to check the code itself.
egos wrote:wichtounet, read floppy sector-by-sector or track-by-track (don't overrun 64-kb boundaries in memory space).
I'll read it track-by-track in the future.
Thank you guys.
Re: [SOLVED] How to read large portion of the floppy with BI
Posted: Sat Dec 07, 2013 3:19 pm
by wichtounet
I'm now reading the floppy sector by sector and I encountered the same error again.
The loader code is now at 0x90:0x0. I'm loading the kernel at 0x100:0x0 sector by sector. Each iteration I add 0x20 to es and bx remains zero all the time.
This time, going from 85 to 87 sectors breaks everything.
Here is the code loading one sector:
Code: Select all
mov ah, 0x2 ; Read sectors from memory
mov al, 1 ; Number of sectors to read
mov ch, [cylinder] ; Cylinder
mov cl, [sector] ; Sector
mov dh, [head] ; Head
mov dl, bootdev ; Drive
int 0x13
I debugged the code, and the call to int 13h fails with these parameters:
Code: Select all
ch = 0x03
cl = 0x0F
dh = 0x0
dl = 0x0
es = 0x0BC0
bx = 0x0
After that, it is just as if I add overwritten the loader code again, but I don't see how it is possible. Does someone have an idea ? Is it some arcane of x86 segmentation ?
Thanks and sorry in advance if the answer seems obvious to you
Re: [SOLVED] How to read large portion of the floppy with BI
Posted: Sun Dec 08, 2013 3:56 am
by M2004
Where do you update CHS values? As you progress reading
sectors you need to update CHS values.
Regards
M2004
Re: [SOLVED] How to read large portion of the floppy with BI
Posted: Sun Dec 08, 2013 4:34 am
by wichtounet
M2004 wrote:Where do you update CHS values? As you progress reading
sectors you need to update CHS values.
Yes I know, the values presented are the values that fail (3,0,15). All the previous 86 sectors are read correctly, but the 87th fails. Moreover, as the 85 previous sectors succeed, I think that my CHS values are correct, it is more a memory error I think, although I don't understand from where.
The values are updated in the loop, here is the complete code:
Code: Select all
KERNEL_BASE equ 0x100 ; 0x100:0x0 = 0x1000
bootdev equ 0x0
sectors equ 87
; Loaded at 0x90:0x0
second_step:
mov ax, 0x90
mov ds, ax
; Reset disk drive
xor ax, ax
mov dl, bootdev
int 0x13
jc reset_failed
mov ax, KERNEL_BASE
mov es, ax
xor di, di
.next:
xor bx, bx
mov ah, 0x2 ; Read sectors from memory
mov al, 1 ; Number of sectors to read
mov ch, [cylinder] ; Cylinder
mov cl, [sector] ; Sector
mov dh, [head] ; Head
mov dl, bootdev ; Drive
int 0x13
jc read_failed
test ah, ah
jne read_failed
cmp al, 1
jne read_failed
mov si, star
call print_16
inc di
cmp di, sectors
jne .continue
mov si, kernel_loaded
call print_line_16
;Run the kernel
jmp dword KERNEL_BASE:0x0
.continue:
mov cl, [sector]
inc cl
mov [sector], cl
cmp cl, 19
jne .next_sector
mov cl, 1
mov [sector], cl
mov dh, [head]
inc dh
mov [head], dh
cmp dh, 2
jne .next_sector
xor dh, dh
mov [head], dh
mov ch, [cylinder]
inc ch
mov [cylinder], ch
.next_sector:
mov ax, es
add ax, 0x20 ; 0x20:0x0 = 512 (sector size)
mov es, ax
jmp .next
reset_failed:
mov si, reset_failed_msg
call print_line_16
jmp error_end
read_failed:
mov si, read_failed_msg
call print_line_16
error_end:
mov si, load_failed
call print_line_16
jmp $
; Variables
sector db 1
head db 0
cylinder db 1
; Constant Datas
load_kernel db 'Attempt to load the kernel...', 0
kernel_loaded db 'Kernel fully loaded', 0
star db '*', 0
reset_failed_msg db 'Reset disk failed', 0
read_failed_msg db 'Read disk failed', 0
load_failed db 'Kernel loading failed', 0
Re: [SOLVED] How to read large portion of the floppy with BI
Posted: Sun Dec 08, 2013 11:40 am
by Minoto
An observation and a suggestion...first, you're placing your stage 2 loader at 0x900, then using it to load your kernel starting at 0x1000. However, your stage 2 is longer than 256 bytes, so you're overwriting a bit of your load_failed message. That's not the cause of your problem, but it's still something you'll want to fix.
When the read fails, instead of just printing an error message and hanging, try using function 1 of int 0x13 to see what went wrong...that might help you narrow down the list of possible causes.
Re: [SOLVED] How to read large portion of the floppy with BI
Posted: Sun Dec 08, 2013 2:04 pm
by wichtounet
Thanks Minoto
Minoto wrote:An observation and a suggestion...first, you're placing your stage 2 loader at 0x900, then using it to load your kernel starting at 0x1000. However, your stage 2 is longer than 256 bytes, so you're overwriting a bit of your load_failed message. That's not the cause of your problem, but it's still something you'll want to fix.
Sorry, but 0x1000 - 0x900 is not equal to 0x100 (256) but 0x700 (1792) which is large enough to hold my stage2.
Minoto wrote:When the read fails, instead of just printing an error message and hanging, try using function 1 of int 0x13 to see what went wrong...that might help you narrow down the list of possible causes.
That is a good idea, thanks , I'll do that once the current bug is fixed
Re: [SOLVED] How to read large portion of the floppy with BI
Posted: Sun Dec 08, 2013 2:29 pm
by Minoto
wichtounet wrote:Minoto wrote:An observation and a suggestion...first, you're placing your stage 2 loader at 0x900, then using it to load your kernel starting at 0x1000. However, your stage 2 is longer than 256 bytes, so you're overwriting a bit of your load_failed message. That's not the cause of your problem, but it's still something you'll want to fix.
Sorry, but 0x1000 - 0x900 is not equal to 0x100 (256) but 0x700 (1792) which is large enough to hold my stage2.
You're right...I was writing in hexadecimal but thinking in decimal. Sorry!