Weird int 0x13 behaviour in real environment

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.
AlfredTH
Posts: 9
Joined: Tue Mar 05, 2019 12:44 pm

Re: Weird int 0x13 behaviour in real environment

Post by AlfredTH »

Schol-R-LEA wrote:
I don't know if this was necessary, anyway thanks for the advices... It's been a month already since I read multiple tutorials, source codes and documentation for this project, although this bootloader stuff seemed more straightforward...
MichaelPetch wrote:
Thanks for the example of Partition Table and indeed, it prints "Hello world!" ! This, indeed, helps a lot :D
The upload command :
FASM.EXE osdev_test.asm ath_os.bin && dd if=ath_os.bin od=\\.\g: bs=512 count=2 (count unnecessary)
This makes me conclude :
- Without using "od" with the dd program on windows, the actual medium where my bootloader was written was a partition.
- When writing correctly using "od", my laptop requires a partition table to allow proper code execution in sector 1.
When I saw this example of partition table on other forums I thought this was an invalid, to-modify one. Apparently it is a wrong thought !

Thanks a lot, Now this problem seem solved because even if an "X" is not printed, a "J" poped on the screen with my new bootloader xD
I think I can work this out, Now that there are no longer null bytes in the buffer for sector 2.
Huge thanks to this community for helping me intensely ! :)
I'll post a final answer with the complete code printing "X" to the screen, once it will work ;)
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Weird int 0x13 behaviour in real environment

Post by SpyderTL »

Check what is in DL on both systems at boot. Also, check the result returned by INT 13h on both systems. This might shed some light on the problem.

You may also want to try calling the newer INT 13h methods that allow you to specify a linear block number instead of the CHS values.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
MichaelPetch
Member
Member
Posts: 798
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Weird int 0x13 behaviour in real environment

Post by MichaelPetch »

Some BIOSes that believe they are dealing with partitioned media will attempt to locate a partition table (with an active entry) and then start executing the code in the first sector of the drive. Other BIOSes may go one further. They may look for an active partition table in the first sector (MBR) and actually load the volume boot record (VBR) for the active partition to physical address 0x07c00 and transfer control to it completely by passing what may have been in the MBR (the first sector of the drive)

Part of me thinks your BIOS may be doing the latter. When you have Windows format a USB drive it creates it as partitioned media. It places an MBR in the first sector of the drive (LBA=0). This includes placing a partition table at the end of the MBR with one of the partition entries that is marked active. When you were using DD with the OF= option originally you were writing to the first sector of the partition. I suspect your BIOS was actually running the VBR of that partition directly so it appeared to do something (albeit not what was expected). When it came time read more sectors from the disk your code tried to read them relative to the beginning of the drive. Unfortunately your DD placed them relative to the beginning of the partition instead so you ended up reading sectors after the MBR that didn't have the code/data you expected because they were placed in the partition.

The trick in the bootloader I presented is that it points the active partition back to the beginning of the drive(not the beginning of an actual partition). So if your BIOS tries to read a VBR directly from an active partition, this MBR's partition table makes the MBR a VBR as well. Of course you need to use DD with the OD= if you intend to write sectors relative to the beginning of the drive where your own code expects them to be,
AlfredTH
Posts: 9
Joined: Tue Mar 05, 2019 12:44 pm

Re: Weird int 0x13 behaviour in real environment

Post by AlfredTH »

SpyderTL wrote:Check what is in DL on both systems at boot.
Don't worry, I had almost every of all possible returned by int 0x13, I'll make it read correctly :)
AlfredTH
Posts: 9
Joined: Tue Mar 05, 2019 12:44 pm

Re: Weird int 0x13 behaviour in real environment

Post by AlfredTH »

Here is the complete code, reading sector 2 and printing its content as a null-terminated string ;)
Works on my Toshiba Pro NB10-A & in Qemu :)
You guys are MVPs ! Thanks a lot, Now I can continue this project :D

Code: Select all

org 0x7c00
jmp start
times 3-($-$$) db 0x90

bpbOEM:                 DB "DIY.OS  "
bpbBytesPerSector:      DW 512
bpbSectorsPerCluster:   DB 1
bpbReservedSectors:     DW 1
bpbNumberOfFATs:        DB 2
bpbRootEntries:         DW 224
bpbTotalSectors:        DW 2880
bpbMedia:               DB 0xF0
bpbSectorsPerFAT:       DW 9
bpbSectorsPerTrack:     DW 18
bpbHeadsPerCylinder:    DW 2
bpbHiddenSectors:       DD 0
bpbTotalSectorsBig:     DD 0
bsDriveNumber:          DB 0
bsUnused:               DB 0
bsExtBootSignature:     DB 0x29
bsSerialNumber:         DD "srno"
bsVolumeLabel:          DB "NO NAME    "
bsFileSystem:           DB "FAT12   "

LOAD_ADDRESS equ 0xa000
STACK_ADDRESS equ 0x9000
SECTORS_TO_READ equ 1
START_SECTOR equ 2

print:
	pusha
	mov ah, 0x0e
print_loop:
	mov al, [bx]
	cmp al, 0
	je print_end
	int 0x10
	add bx, 1
	jmp print_loop
print_end:
	mov al, 13
	int 0x10
	mov al, 10
	int 0x10
	popa
	ret

err_msg:db "Disk read error !",0
err_disp:
	mov bx, err_msg
	call print
	jmp $

disk_ok:db "Disk read w/out error ! Content :",0
init_drive:db 0
start:
	; setup segments and stack
	cli
	xor bx, bx
	mov ss, bx
	mov sp, STACK_ADDRESS
	mov ds, bx
	mov es, bx
	mov fs, bx
	mov gs, bx
	sti
	
	xor bx, bx
	mov ah, 0x02
	mov al, SECTORS_TO_READ
	mov ch, bl ; cylinder 0
	mov cl, START_SECTOR
	mov dh, bl ; head 0
	mov es, bx
	mov bx, LOAD_ADDRESS ; es:bx = 0:0x9000
	int 0x13
	jc err_disp
	
	cmp al, SECTORS_TO_READ ; check how many sectors were read, must be SECTORS_TO_READ
	jne err_disp
	
	mov bx, disk_ok ; tell the user there was no error
	call print
	
	mov bx, LOAD_ADDRESS ; print content of LOAD_ADDRESS
	call print

	jmp $

times 446-($-$$) db 0   ; Pad with 0s up until first partition entry
db 0x80                 ; 0x80 = Active boot partition, 0x00=inactive
db 0x00, 0x01, 0x00     ; CHS of first absolute sector (MBR) of hard drive
                        ;     Head=0, Sector=1, Cylinder=0
db 0x0c                 ; Partition type (has to be non-zero)
                        ;     0x0c = Win 95 FAT32 (LBA)
db 0x00, 0x0f, 0x00     ; CHS of last absolute sector (MBR) of hard drive
                        ;     Head=0, Sector=1, Cylinder=0
                        ;     We are effectively saying Size of partition is 1 sector
dd 0x0                  ; LBA of first absolute sector (0=MBR)
dd 0xf                  ; Number of sectors in partition. We set it to 1 but if you
                        ;     wish you could set it to the number of sectors on the disk
times 510-($-$$) db 0
dw 0xaa55 ; magic bytes

db "This is data from sector 2 ;)",0
Post Reply