OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Apr 25, 2024 2:47 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: bootsector: BIOS int 0x13 cannot read sectors
PostPosted: Mon Aug 19, 2013 3:57 pm 
Offline

Joined: Sun Apr 24, 2011 10:51 am
Posts: 13
Hi,
i just re-started osdevving after a long break (the last tarball of my OS is dated October 2011... ugh) by writing a bootloader.
My OS made use of GRUB to boot and supported both the Multiboot and Multiboot2 protocols; i had the feel of being too far from the machine and learn too little despite the huge time effort so i've ended up losing interest in the project.

Now, the problem is that on some hardaware/emulators i simply can't load the stage2 correctly.

This is the stage2 test code:

Code:
[bits 16]
dw 0xFEDE ; signature; must remain first

; used the stack just in order to test it ;-)
push 'K'
push 'O'

pop ax
mov ah, 0x0E
int 0x10

pop ax
mov ah, 0x0E
int 0x10

Hang:
cli
hlt
jmp Hang



The following PCs execute the code correctly and display 'OK' on the screen (some computer names are made up, cannot remember the model):
  • JPC - emulator (from floppy)
  • JPC - emulator (from disk)
  • HP blue (from floppy)
  • HP blue (from disk)
  • HP black (from disk)
  • Abaco (from disk)
  • Fujitsu FMV-475NU/S (from floppy)
  • DELL Inspiron N411Z (from disk)

The following PCs fail miserably the task:
  • qemu - emulator (floppy): "Wrong signature detected, hang." (explained later)
  • qemu - emulator (disk): black screen, just hangs somewhere
  • Toshiba NB100 (disk): skip to hard disk and boot the installed system

The Toshiba's behaviour is a mistery to me but for what concerns qemu, it seems that there is no trace of the loaded sector in memory (see http://imageshack.us/photo/my-images/716/bzd.png/ )

The stage1's loading code looks like this (sorry for the length):
Code:
;------------------------------------------------------------------------------
; reset drive and load sectors
;------------------------------------------------------------------------------

mov cx, 0x0003

DriveReset:

mov ah, 0x00
mov dl, [drive_id]
int 0x13

jnc DriveResetDone
loop DriveReset
jc LoadFailure

DriveResetDone:

;------------------------------------------------------------------------------

mov cx, 0x0003

DriveRead:

mov ax, LOAD_SEGMENT
mov es, ax  ; set segment
mov bx, 0x0 ; set offset

mov ah, 0x02  ; load disk data to ES:BX
mov al, 17    ; number of sectors to load
mov ch, 0x00  ; cylinder
mov cl, 0x02  ; sector
mov dh, 0x00  ; head
mov dl, [drive_id]
int 0x13

jnc DriveReadDone
loop DriveRead
jc LoadFailure

DriveReadDone:

;------------------------------------------------------------------------------
; check signature
;------------------------------------------------------------------------------

mov ax, LOAD_SEGMENT
mov es, ax  ; set segment
mov si, 0x0 ; set offset

mov ax, [es:si]
cmp ax, LOAD_SIGNATURE
jne WrongSignature

jmp LOAD_SEGMENT:2 ; jump to loaded code skipping the signature


In two days i couldn't find any obvious error (maybe for the lack of experience), please help.
If you think it's necessary, i can post the whole stage1 code.

Thanks


Top
 Profile  
 
 Post subject: Re: bootsector: BIOS int 0x13 cannot read sectors
PostPosted: Mon Aug 19, 2013 5:24 pm 
Offline
Member
Member

Joined: Fri Nov 16, 2007 1:59 pm
Posts: 612
BIOS int 0x13 can read sectors. I checked :P

What values do ds, ss and sp have?

Code:
mov cx, 0x0003

DriveRead:
...
mov ch, 0x00  ; cylinder
mov cl, 0x02  ; sector
...
loop DriveRead
Well done :D

This is risky too:
Code:
mov cx, 0x0003

DriveReset:

mov ah, 0x00
mov dl, [drive_id]
int 0x13

jnc DriveResetDone
loop DriveReset

_________________
If you have seen bad English in my words, tell me what's wrong, please.


Top
 Profile  
 
 Post subject: Re: bootsector: BIOS int 0x13 cannot read sectors
PostPosted: Tue Aug 20, 2013 12:55 am 
Offline

Joined: Sun Apr 24, 2011 10:51 am
Posts: 13
egos wrote:
BIOS int 0x13 can read sectors. I checked :P


aha, yeah. Most of the time at least :-)

egos wrote:
What values do ds, ss and sp have?


DS = 0x7C0
SS = 0x0050
SP = 0x5500

Code:
%define CODE_SEGMENT   0x07C0
%define DATA_SEGMENT   CODE_SEGMENT

; stack is located in the lowest 'guaranteed free for use' RAM slot
; (0x500 to 0x7BFF, almost 30kB)
%define STACK_SEGMENT  0x0050
%define STACK_OFFSET   0x5000 ; 20kB = 20480B, more than enough

; the next stage will be loaded just after the end of the bootsector extending
; for 17 sectors in order to avoid putting the CHS-LBA address translation code
; in the bootsector (8.5kB should be enough for the higher 16-bit loader stage)
%define LOAD_SEGMENT   (CODE_SEGMENT + 0x0020)
%define LOAD_SIGNATURE 0xFEDE


egos wrote:
This is risky too:
Code:
mov cx, 0x0003

DriveReset:

mov ah, 0x00
mov dl, [drive_id]
int 0x13

jnc DriveResetDone
loop DriveReset



why?

Thanks


Top
 Profile  
 
 Post subject: Re: bootsector: BIOS int 0x13 cannot read sectors
PostPosted: Tue Aug 20, 2013 1:23 am 
Offline
Member
Member

Joined: Fri Nov 16, 2007 1:59 pm
Posts: 612
wikiwolf wrote:
why?
cx value can be corrupted by BIOS.

_________________
If you have seen bad English in my words, tell me what's wrong, please.


Top
 Profile  
 
 Post subject: Re: bootsector: BIOS int 0x13 cannot read sectors
PostPosted: Tue Aug 20, 2013 1:42 am 
Offline

Joined: Sun Apr 24, 2011 10:51 am
Posts: 13
egos wrote:
wikiwolf wrote:
why?
cx value can be corrupted by BIOS.


Ah, didn't knew that.

I tryed eliminating the loop and the 'hanging' behaviour of qemu (from disk) disappeared, now it correctly says "Unable to load next stage, hang." <- Cool!

So:
qemu (floppy) : "Wrong signature detected, hang." means that the sector is loaded but there is no trace of it in memory
qemu (disk) : "Unable to load next stage, hang." means that the loading failed

While the second behaviour can happen occasionally, i don't get the first one, or better:
i expect that if the 'int 0x13' returns no error (carry flag is not set), my code must be in memory.

I'll retry on real hardware as soon as i can to check the Toshiba's behaviour as well.

There is some way to reliably perform the loop instruction in real mode or should i do loops manually by setying-up a separate counter to decrease?

Thanks


Top
 Profile  
 
 Post subject: Re: bootsector: BIOS int 0x13 cannot read sectors
PostPosted: Tue Aug 20, 2013 2:07 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9301
Location: On the balcony, where I can actually keep 1½m distance
Quote:
There is some way to reliably perform the loop instruction in real mode
The loop instruction is perfectly reliable. It always decrements cx and jumps if it's not zero. If you (or the bios in this case) go changing the value of cx within the loop, then you are changing the counter as well. Unfortunately, you can't spawn registers out of nowhere, but you can use memory for that.


tl;dr: use push/pop to cx

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
 Post subject: Re: bootsector: BIOS int 0x13 cannot read sectors
PostPosted: Tue Aug 20, 2013 4:34 am 
Offline

Joined: Sun Apr 24, 2011 10:51 am
Posts: 13
You're right, thanks Combuster.

Just noticed that
Code:
mov ch, 0x00  ; cylinder
mov cl, 0x02  ; sector

was overwriting CX... don't know how i missed it :oops:

Now i've changed the load code fixing the bug, incrementing the number of retries to six and resetting the drive every time the read fails:
Code:
;------------------------------------------------------------------------------
; reset drive and load sectors
;------------------------------------------------------------------------------

mov cx, 0x0006

DriveReset:

mov ah, 0x00
mov dl, [drive_id]
int 0x13

jnc DriveRead
loop DriveReset
jc LoadFailure

DriveRead:

mov ax, LOAD_SEGMENT
mov es, ax  ; set segment
mov bx, 0x0 ; set offset

push cx
mov ah, 0x02  ; load disk data to ES:BX
mov al, 17    ; number of sectors to load
mov ch, 0x00  ; cylinder
mov cl, 0x02  ; sector
mov dh, 0x00  ; head
mov dl, [drive_id]
int 0x13
pop cx

jnc DriveDone
loop DriveReset
jc LoadFailure

DriveDone:

;------------------------------------------------------------------------------
; check signature
;------------------------------------------------------------------------------

mov ax, LOAD_SEGMENT
mov es, ax  ; set segment
mov si, 0x0 ; set offset

mov ax, [es:si]
cmp ax, LOAD_SIGNATURE
jne WrongSignature

jmp LOAD_SEGMENT:2 ; jump to loaded code skipping the signature



With the following results:
  • qemu - emulator (floppy): "Wrong signature detected, hang." -- still weird (int 0x13 return no error codes but the second sector isn't loaded in memory)
  • qemu - emulator (disk): "Unable to load next stage, hang." -- a little better but still not working (loading fails after six retries on an emulator, doesn't sounds right to me)
  • Toshiba NB100 (disk): quick reboot into installed system (without doing the POST)


Top
 Profile  
 
 Post subject: Re: bootsector: BIOS int 0x13 cannot read sectors
PostPosted: Tue Aug 20, 2013 11:34 am 
Offline

Joined: Sun Apr 24, 2011 10:51 am
Posts: 13
OK, i solved the issue with qemu.

stage1 loads 17 sectors for a total of 8.5kB and the stage2 occupies just few bytes, so the stage1 was loading the stage2 and roughly 8.4kB of random crap (i'm not sure how this can affect the running code, however).

Adding
Code:
times (0x2200 - ($ - $$)) db 0x00

at the end of stage2 solved both the issues with qemu.

The Toshiba NB100's behaviour is still weird and i'm starting to think it's due to a bugged BIOS since it's the only machine out of eleven where the code does not work.

Well, i'm happy enough with having qemu work, the thread can be closed.
Many thanks to egos and Combuster :D


Top
 Profile  
 
 Post subject: Re: bootsector: BIOS int 0x13 cannot read sectors
PostPosted: Wed Aug 21, 2013 3:56 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9301
Location: On the balcony, where I can actually keep 1½m distance
wikiwolf wrote:
stage1 loads 17 sectors for a total of 8.5kB and the stage2 occupies just few bytes, so the stage1 was loading the stage2 and roughly 8.4kB of random crap (i'm not sure how this can affect the running code, however).
It's called a corrupt disk image. QEmu can't read from such sectors (including the incomplete ones) and will typically load zeroes instead.

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Majestic-12 [Bot], RayanMargham and 242 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group