Int13h AH=42h Boot From Hard Drive just fails [Solved]

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.
User avatar
CmpXchg
Member
Member
Posts: 61
Joined: Mon Apr 28, 2008 12:14 pm
Location: Petrozavodsk, Russia during school months, Vänersborg Sweden in the summertime

Int13h AH=42h Boot From Hard Drive just fails [Solved]

Post by CmpXchg »

Hi!

I'm working an a project of an OS, but gotten stuck with the bootsector code.

Problem: Bootsector fails to load 2nd stage loader.

It's designed for NTFS partitions, it's supposed to load some number of sectors immediately following it on the partition. But Int13h AH=42h returns AH=1 with CF set. Couldn't figure out why so far.

Here's the code that fails:

Code: Select all

;/*
;* bootldr.asm *
;* NTFS-specific *
;* Bootsector is supposed to start with EB 52 *
;*/
        org 7C54h

;NTFS Bootsector Structures
        [section .bpb]
absolute        7C1Ch
BPB_HiddSec                     resd    1

absolute        7C28h
ExtBPB_TotalSectors             resq    1
ExtBPB_$MFTCluster              resq    1
ExtBPB_$MFTMirrCluster          resq    1
ExtBPB_FileRecordSize           resd    1
ExtBPB_IndexBlockSize           resd    1
ExtBPB_SerialNumber             resq    1
ExtBPP_Checksum                 resd    1


;My bootsector code
        [section .code align=2]
start:
        xor     ax,ax
        mov     ds,ax
        mov     es,ax
        cli
        mov     ss,ax
        mov     sp,7C00h
        sti

        push    first_message
        call    print_string
        
        push    word (bootldr_end - sector1)/512 + 1            ;evaluates to 1
        push    word sector1                                    ;offset
        push    ds                                              ;segment
        push    dword [BPB_HiddSec]                             ;LBA
        call    load_sectors

        jmp     sector1

;/* 
;* Realmode Int13h AH=42h sector loading routine *
;*/
load_sectors:
        push    bp
        mov     bp,sp

%define lba     (bp+4)
%define seg     (bp+8)
%define ofs     (bp+10)
%define nsect   (bp+12)
        
        push    dword 0
        push    dword [lba]             ;LBA
        push    word [seg]              ;segment
        push    word [ofs]              ;offset
        push    word [nsect]            ;number of sectors
        push    word 10h                ;10h, 0h.

        mov     ah,42h
        mov     si,sp
        mov     dl,80h
        int     13h

        jc      os_failure
        test    ah,ah
        jnz     os_failure

        leave
        retn    10

os_failure:
        push    fail_message
        call    print_string
        mov     al,ah
        call    print_al

        xor     ax,ax
        int     16h
        int     19h

;Text messages
first_message   db      "Hi! I'm a boot sector! Let's start up...",13,10,0

fail_message    db      "Didn't even make it past the bootsector. Goodbye ;(",13,10
                db      'INT13 Failed with AH=',0

;<here are some printing routines for debug>
;/* 
;* Realmode printing routine *
;*/
print_string:
        mov     bp,sp
        mov     si,word [bp+2]
        pusha
        mov     ah,0Eh
        cld
.print_loop:
        lodsb
        test    al,al
        jz      .end_print
        int     10h
        jmp     short .print_loop
.end_print:
        popa
        retn    2

times   510-54h-($-$$) db 0

db      55h,0AAh
;======================================== The End of Sector 0

; The Start of Sector 1 ======================================
sector1:
        push    message2
        call    print_string
        xor     ax,ax
        int     16h
        int     19h

;/* TODO:
;* -) Parse the NTFS root dir for Kernel.exe
;* -) Load it up above 1 Mb using INT13h AH=42h
;* -) Set up basic PM
;* -) Jump to KernelEntry()
;*/

message2        db      "Ok, let's load the Kernel.exe and set up PM",0                 

bootldr_end:
How to reproduce: Compile with NASM -f bin and run in QEMU or even on real hardware, same thing. The output binary file is supposed to be pasted into an NTFS bootsector at offset 0x54.

Please give your perspective. Slap me if this has been answered somewhere before :oops:
Last edited by CmpXchg on Wed Jun 10, 2009 1:41 pm, edited 1 time in total.
Every Man Must Learn David DeAngelo's Stuff, Period.
http://www.doubleyourdating.com/Catalog
User avatar
Masterkiller
Member
Member
Posts: 153
Joined: Sat May 05, 2007 6:20 pm

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by Masterkiller »

Last 15 times I redesign my loader I used this:
http://www.ctyme.com/intr/rb-0706.htm
to check if the specified device support extended functions.
It's all depends on your hardware if it has LBA access in BIOS. LBA Access (Extended function) in BIOS for a bootable device is not the save as LBA access through the I/O ports. So even you hard disk is 500GB, that does not mean BIOS will support LBA access.
ALCA OS: Project temporarity suspended!
Current state: real-mode kernel-FS reader...
User avatar
alethiophile
Member
Member
Posts: 90
Joined: Sat May 30, 2009 10:28 am

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by alethiophile »

Try running it in Bochs. It tends to emit more helpful errors than Qemu.
If I had an OS, there would be a link here.
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by mathematician »

The fact that addresses are always written seg:offset means it is an easy mistake to make, but you are pushing the seg and offset in the wrong order. Seg should be the most significant word of a double word address. For example, 1234:5678h would appear in memory as:

dw 5678h.........................offset - least sig word (sp= 98 say)
dw 1234h.........................seg - most sig word (sp= 100 say)
The continuous image of a connected set is connected.
User avatar
kop99
Member
Member
Posts: 120
Joined: Fri May 15, 2009 2:58 am

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by kop99 »

but you are pushing the seg and offset in the wrong order.
mathematician, you are wrong.
CmpXchg's pushing order is right.
User avatar
kop99
Member
Member
Posts: 120
Joined: Fri May 15, 2009 2:58 am

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by kop99 »

CmpXchg, make sure there is right value...

Code: Select all

push    word (bootldr_end - sector1)/512 + 1            ;evaluates to 1
User avatar
Masterkiller
Member
Member
Posts: 153
Joined: Sat May 05, 2007 6:20 pm

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by Masterkiller »

kop99 wrote:
but you are pushing the seg and offset in the wrong order.
mathematician, you are wrong.
CmpXchg's pushing order is right.
Actually all that he pushes is wrong. Structure must be as follows:

Code: Select all

+0: word 0x10
+2: word NumberOfSectors
+4: word Offset
+6: word Segment
+8: Qword LBA
You do not specify the size of structure.
You do not push the high double-word of the 64-bit value of LBA.
You start pushing from +0 part. You stack DEcrements on every pushing, not INcrement, so the structure you got is in reverse order.

P.S. oops, I looked in the wrong place e.g. pushing before call, not before int. Anyway no guarantees that extended read is supported for the current device. Also try to use an DL returned by BIOS, not 0x80 :)
Last edited by Masterkiller on Mon Jun 08, 2009 3:50 am, edited 1 time in total.
ALCA OS: Project temporarity suspended!
Current state: real-mode kernel-FS reader...
User avatar
kop99
Member
Member
Posts: 120
Joined: Fri May 15, 2009 2:58 am

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by kop99 »

Masterkiller, your structure is right.

Code: Select all

+0: word 0x10
+2: word NumberOfSectors
+4: word Offset
+6: word Segment
+8: Qword LBA
so, push order is following.

Code: Select all

+8: Qword LBA
+6: word Segment
+4: word Offset
+2: word NumberOfSectors
+0: word 0x10
and CmpXchg's code is following.

Code: Select all

        push    dword 0
        push    dword [lba]             ;LBA
        push    word [seg]              ;segment
        push    word [ofs]              ;offset
        push    word [nsect]            ;number of sectors
        push    word 10h                ;10h, 0h.
So, isn't he all right?
I think you have a little mistake.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by pcmattman »

@OP: Will this have the correct value when popped as a QWord? Make sure your endianness is correct.

Code: Select all

        push    dword 0
        push    dword [lba]             ;LBA
Also,
Try running it in Bochs. It tends to emit more helpful errors than Qemu.
You can also enable debug logging on the device you're reading from, which will let you see exactly what's happening.
User avatar
Firestryke31
Member
Member
Posts: 550
Joined: Sat Nov 29, 2008 1:07 pm
Location: Throw a dart at central Texas
Contact:

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by Firestryke31 »

Is the packet address DWORD aligned? I've had problems when it wasn't. Aligning the stack is rather simple, try something along the lines of this (Intel syntax):

Code: Select all

 push bp
 mov bp, sp
 mov ax, sp
 and ax, 3
 jz .noAlign
 sub sp, ax
.noAlign:
 ;; Pushing packet here!

 ;; When done with packet, do this
 mov sp, bp
 pop bp
Owner of Fawkes Software.
Wierd Al wrote: You think your Commodore 64 is really neato,
What kind of chip you got in there, a Dorito?
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by mathematician »

kop99 wrote:
but you are pushing the seg and offset in the wrong order.
mathematician, you are wrong.
CmpXchg's pushing order is right.
After a far call, the stack looks like this:

arg1
arg2
cs
ip

After a real mode interrupt, it looks like this:

flags
cs
ip

stored in memory a far pointer looks like this:

dw offset, seg

The seg is always the most significant word. The thing which confuses the issue is so called "back words storage"
ip
The continuous image of a connected set is connected.
User avatar
kop99
Member
Member
Posts: 120
Joined: Fri May 15, 2009 2:58 am

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by kop99 »

mathematician, if you point that code, i think there is no mistake.

Code: Select all

        push    word [seg]              ;segment
        push    word [ofs]              ;offset
dw offset, seg

The seg is always the most significant word. The thing which confuses the issue is so called "back words storage"
ip
in IA, memory order for Disk Address Packet is, first offset, and then segment.
geppyfx
Member
Member
Posts: 87
Joined: Tue Apr 28, 2009 4:58 pm

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by geppyfx »

Right, voting that original(1st) post has correct code for offset,segment.
Segment is at highest addr in the ram and pushed first, SP decreased; offset at the lowest and pushed second.
mathematician wrote: dw 5678h.........................offset - least sig word (sp= 98 say)
dw 1234h.........................seg - most sig word (sp= 100 say)
mathematician probably looked at 1st 4 pushes outside the load_sectors function and decided that CmpXchg pushes them in same order for int13

There is one big flaw in the CmpXchg code however. But its not the problem why code is not working. PUSH uses SS and int13h uses DS. Consciously or not but CmpXchg zeroed them both, this is why code still working.
User avatar
CmpXchg
Member
Member
Posts: 61
Joined: Mon Apr 28, 2008 12:14 pm
Location: Petrozavodsk, Russia during school months, Vänersborg Sweden in the summertime

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by CmpXchg »

Okay...
Wow, I'm impressed, so many people willing to help. Thanks!

Now... to make sure everyone feels heard, let me see what we've got here.
Masterkiller wrote:It's all depends on your hardware if it has LBA access in BIOS. LBA Access (Extended function) in BIOS for a bootable device is not the save as LBA access through the I/O ports. So even you hard disk is 500GB, that does not mean BIOS will support LBA access.
I'm damn sure BIOS supports LBA access, it just returns an error, but the functions are there. Windows XP loader code uses them every time I turn this thing on. And they must be supported in virtual machines.
pcmattman wrote:Also,
alethiophile wrote:Try running it in Bochs. It tends to emit more helpful errors than Qemu.
You can also enable debug logging on the device you're reading from, which will let you see exactly what's happening.
Well, yeah, but right now with Qemu, I can just go: qemu -hdb d: -L <whatever>
and it boots my D: partiton. The problem is: how to do the same with Bochs?

Next, that fascinating debate around pushing order... I believe I'm pushing it right. In memory, offset gets pushed at lower address (98, say) and the seg gets pushed to a higher address (100, say). So, reversely, the seg has to be pushed first. Period.
mathematician wrote:After a far call, the stack looks like this:
...
After a real mode interrupt, it looks like this:
...
stored in memory a far pointer looks like this:
...
dw offset, seg
Nah, these are all near relative calls. And yeah, dw offset, seg - that's how exactly it gets stored in memory. No question.

@pcmattman: the endianness does seem to be correct.

Now, if the structure content is right, what is the actual problem, then?
Firestryke31 wrote:Is the packet address DWORD aligned? I've had problems when it wasn't.
Hmm, that looks like a cause for trouble. Frankly, alignment was the last thing on my mind when I wrote this... I'll play with this.
geppyfx wrote:There is one big flaw in the CmpXchg code however. But its not the problem why code is not working. PUSH uses SS and int13h uses DS. Consciously or not but CmpXchg zeroed them both, this is why code still working.
I did it consciously :D Still not the issue, then! One thing I am thinking about is that INT13 might modify BP... which would mess up the stack completely, of course.

Keep brainstorming, please...
Every Man Must Learn David DeAngelo's Stuff, Period.
http://www.doubleyourdating.com/Catalog
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

Re: Int13h AH=42h Boot From Hard Drive just fails

Post by Love4Boobies »

Your origin is 0754h (as opposed to 7C00h) and thus all offsets are wrong (jumps, variables, etc).
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
Post Reply