[SOLVED] How to read large portion of the floppy with BIOS ?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
wichtounet
Member
Member
Posts: 90
Joined: Fri Nov 01, 2013 4:05 pm
Location: Fribourg, Switzerland
Contact:

[SOLVED] How to read large portion of the floppy with BIOS ?

Post 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
Last edited by wichtounet on Sun Jan 19, 2014 2:35 pm, edited 3 times in total.
Thor Operating System: C++ 64 bits OS: https://github.com/wichtounet/thor-os
Good osdeving!
Nable
Member
Member
Posts: 453
Joined: Tue Nov 08, 2011 11:35 am

Re: How to read large portion of the floppy with BIOS ?

Post 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?
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: How to read large portion of the floppy with BIOS ?

Post by egos »

wichtounet, read floppy sector-by-sector or track-by-track (don't overrun 64-kb boundaries in memory space).
If you have seen bad English in my words, tell me what's wrong, please.
User avatar
wichtounet
Member
Member
Posts: 90
Joined: Fri Nov 01, 2013 4:05 pm
Location: Fribourg, Switzerland
Contact:

Re: How to read large portion of the floppy with BIOS ?

Post 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.
Thor Operating System: C++ 64 bits OS: https://github.com/wichtounet/thor-os
Good osdeving!
User avatar
wichtounet
Member
Member
Posts: 90
Joined: Fri Nov 01, 2013 4:05 pm
Location: Fribourg, Switzerland
Contact:

Re: [SOLVED] How to read large portion of the floppy with BI

Post 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
Thor Operating System: C++ 64 bits OS: https://github.com/wichtounet/thor-os
Good osdeving!
M2004
Member
Member
Posts: 65
Joined: Sun Mar 07, 2010 2:12 am

Re: [SOLVED] How to read large portion of the floppy with BI

Post by M2004 »

Where do you update CHS values? As you progress reading
sectors you need to update CHS values.

Regards
M2004
User avatar
wichtounet
Member
Member
Posts: 90
Joined: Fri Nov 01, 2013 4:05 pm
Location: Fribourg, Switzerland
Contact:

Re: [SOLVED] How to read large portion of the floppy with BI

Post 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
Thor Operating System: C++ 64 bits OS: https://github.com/wichtounet/thor-os
Good osdeving!
User avatar
Minoto
Member
Member
Posts: 89
Joined: Thu May 12, 2011 7:24 pm

Re: [SOLVED] How to read large portion of the floppy with BI

Post 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.
Those who understand Unix are doomed to copy it, poorly.
User avatar
wichtounet
Member
Member
Posts: 90
Joined: Fri Nov 01, 2013 4:05 pm
Location: Fribourg, Switzerland
Contact:

Re: [SOLVED] How to read large portion of the floppy with BI

Post 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 :)
Thor Operating System: C++ 64 bits OS: https://github.com/wichtounet/thor-os
Good osdeving!
User avatar
Minoto
Member
Member
Posts: 89
Joined: Thu May 12, 2011 7:24 pm

Re: [SOLVED] How to read large portion of the floppy with BI

Post 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.
#-o You're right...I was writing in hexadecimal but thinking in decimal. Sorry!
Those who understand Unix are doomed to copy it, poorly.
Post Reply