OSDev.org https://forum.osdev.org/ |
|
Making a bootable image https://forum.osdev.org/viewtopic.php?f=1&t=37405 |
Page 3 of 7 |
Author: | PeterX [ Sun Nov 01, 2020 9:58 am ] |
Post subject: | Re: Making a bootable image |
The first sector of a FAT disk/partition is a mix of code and file system data. 1.) In the code you must skip over the data (the BIOS Parameter block) and continue after the BPB. 2.) In the script/makefile you must write only the code to the disk image. Otherwise you erase the FAT file system data. |
Author: | Bonfra [ Sun Nov 01, 2020 10:06 am ] |
Post subject: | Re: Making a bootable image |
PeterX wrote: In the code you must skip over the data (the BIOS Parameter block) and continue after the BPB How large is the BPB? does it depends on the file system? From where should I should start adding code? PeterX wrote: Otherwise you erase the FAT file system data. Is this also in the BPB or is some other part of the disk to not override? |
Author: | PeterX [ Sun Nov 01, 2020 10:12 am ] |
Post subject: | Re: Making a bootable image |
Bonfra wrote: PeterX wrote: In the code you must skip over the data (the BIOS Parameter block) and continue after the BPB How large is the BPB? does it depends on the file system? From where should I should start adding code? PeterX wrote: Otherwise you erase the FAT file system data. Is this also in the BPB or is some other part of the disk to not override? Yes, it depends on the file system. Here is a list of the different DOS versions and their BPB: https://en.wikipedia.org/wiki/BIOS_parameter_block I suggest you take the DOS 7.1 FAT32 structure which goes from offset 3 to offset 95. So from offset 96 on it's ok to write code. No, there is no other data that should not be overwritten. When I talk about FAT file system data and BPB I mean the same. |
Author: | Bonfra [ Sun Nov 01, 2020 10:15 am ] |
Post subject: | Re: Making a bootable image |
PeterX wrote: I suggest you take the DOS 7.1 FAT32 structure which goes from offset 3 to offset 95. So from offset 96 on it's ok to write code. 7.1 Is for FAT32, by now I'm using FAT12. Do you think I should just switch to FAT32 or use a FAT12 BPB for now? Or I just ignore that part of the disk to leave compatibiliy for FAT32 and continue using FAT12? |
Author: | PeterX [ Sun Nov 01, 2020 10:17 am ] |
Post subject: | Re: Making a bootable image |
Bonfra wrote: Or I just ignore that part of the disk to leave compatibiliy for FAT32 and continue using FAT12? I suggest yes. But it's up to you. All three options should work (somehow). |
Author: | Bonfra [ Sun Nov 01, 2020 10:35 am ] |
Post subject: | Re: Making a bootable image |
So in the bootloader file I do something like this: Code: jmp 0x7C00 : boot biosParameterBlock: times 0x52-($-$$) db 0 ; BPB 7.1 FAT32 ends at 0x52. boot: ; Actual boot code And I need to copy the jump and the boot in the partition.dd excluding the biosParameterBlock. The problem is that even if I copy only the first byte the partition is no more recognized: Code: dd if=bin/boot/boot.bin of=partition.dd seek=0 count=1 conv=notrunc bs=1 This is the partition before copy: Code: EB 3C 90 6D 6B 66 73 2E-66 61 74 00 02 04 04 00 [...] This is the partition after copy: Code: EA 3C 90 6D 6B 66 73 2E-66 61 74 00 02 04 04 00 [...]
|
Author: | PeterX [ Sun Nov 01, 2020 10:47 am ] |
Post subject: | Re: Making a bootable image |
Code: jmp 0x7C00 : boot No, that's a far jump. It takes 5 bytes. But you have only room of 3 bytes. So use a near jump Code: jmp boot or a short jump Code: jmp short boot nop I recommend the short JMP. |
Author: | Bonfra [ Sun Nov 01, 2020 10:52 am ] |
Post subject: | Re: Making a bootable image |
In the bootloader: Code: jmp short boot In the terminal: Code: dd if=bin/boot/boot.bin of=partition.dd seek=0 count=1 conv=notrunc bs=3 And the image results in: Code: EB 5E 00 6D 6B 66 73 2E-66 61 74 00 02 04 04 00 [...] But the image is still marked as unknown |
Author: | PeterX [ Sun Nov 01, 2020 10:54 am ] |
Post subject: | Re: Making a bootable image |
Bonfra wrote: In the bootloader: Code: jmp short boot In the terminal: Code: dd if=bin/boot/boot.bin of=partition.dd seek=0 count=1 conv=notrunc bs=3 And the image results in: Code: EB 5E 00 6D 6B 66 73 2E-66 61 74 00 02 04 04 00 [...] Add the "nop". Some BIOS check for that NOP. |
Author: | Bonfra [ Sun Nov 01, 2020 11:06 am ] |
Post subject: | Re: Making a bootable image |
PeterX wrote: Add the "nop". Some BIOS check for that NOP. It was this! Now the image is valid. I'll do some testing to load the bootloader and I'll let you know. Thanks |
Author: | Bonfra [ Sun Nov 01, 2020 12:00 pm ] |
Post subject: | Re: Making a bootable image |
Ok the partition works perfectly. It is created with this script: Code: #Create the partition dd if=/dev/zero of=partition.dd bs=512 count=65536 # count = [ K = megabyte; K*(1024)^2/512 ] mkfs.vfat -F 16 partition.dd #Add file to the partition mcopy -i partition.dd path/to/file.eg ::/ #Add the bootloader to the partition dd if=path/to/boot.bin of=partition.dd seek=0 count=1 conv=notrunc bs=3 dd if=path/to/boot.bin of=partition.dd seek=83 seek=83 skip=83 count=$[512-83] conv=notrunc bs=1 Then I Create the disk image and copy the partition in it: Code: #Create the Disk image dd if=/dev/zero of=disk.dd bs=512 count=$[2048+65536] echo -e "n \n p \n \n \n \n t \n 6\n a \n w" | fdisk disk.dd #Load the MBR dd if=bin/boot/mbr.bin of=disk.dd seek=0 count=1 conv=notrunc bs=436 #Add the partition to the disk dd if=partition.dd of=disk.dd conv=notrunc bs=512 seek=2048 If I boot just the partition.dd with: Code: qemu-system-x86_64 partition.dd It prints "Hello, World!" but if i boot the disk.dd it prints nothing, instead it clears the screen (which I think is not a good thing). Is it something with the disk reading part? This is the code for the MBR: Code: bits 16
org 0x0600 start: cli ; We do not want to be interrupted xor ax, ax ; 0 AX mov ds, ax ; Set Data Segment to 0 mov es, ax ; Set Extra Segment to 0 mov ss, ax ; Set Stack Segment to 0 mov sp, ax ; Set Stack Pointer to 0 .CopyLower: mov cx, 0x0100 ; 256 WORDs in MBR mov si, 0x7C00 ; Current MBR Address mov di, 0x0600 ; New MBR Address rep movsw ; Copy MBR jmp 0:LowStart ; Jump to new Address LowStart: sti ; Start interrupts mov BYTE [bootDrive], dl ; Save BootDrive .CheckPartitions: ; Check Partition Table For Bootable Partition mov bx, PT1 ; Base = Partition Table Entry 1 mov cx, 4 ; There are 4 Partition Table Entries .CKPTloop: mov al, BYTE [bx] ; Get Boot indicator bit flag test al, 0x80 ; Check For Active Bit jnz .CKPTFound ; We Found an Active Partition add bx, 0x10 ; Partition Table Entry is 16 Bytes dec cx ; Decrement Counter jnz .CKPTloop ; Loop jmp error.noBootablePartition ; ERROR! .CKPTFound: mov WORD [PToff], bx ; Save Offset add bx, 8 ; Increment Base to LBA Address .ReadVBR: mov EBX, DWORD [bx] ; Start LBA of Active Partition mov di, 0x7C00 ; We Are Loading VBR to 0x07C0:0x0000 mov cx, 1 ; Only one sector call ReadSectors ; Read Sector .jumpToVBR: cmp WORD [0x7DFE], 0xAA55 ; Check Boot Signature jne error ; Error if not Boot Signature mov si, WORD [PToff] ; Set DS:SI to Partition Table Entry mov dl, BYTE [bootDrive] ; Set DL to Drive Number jmp 0x7C00 ; Jump To VBR error: jmp hang .noBootablePartition: mov si, Message.Error.NoBootablePartition call BiosPrint jmp hang hang: cli hlt jmp hang absoluteSector db 0x00 absoluteHead db 0x00 absoluteTrack db 0x00 datasector dw 0x0000 cluster dw 0x0000 bpbSectorsPerCluster: DB 1 bpbSectorsPerTrack: DW 18 bpbHeadsPerCylinder: DW 2 bpbBytesPerSector: DW 512 ;********************; ; Convert CHS to LBA ; ; Parameters: ; ; ax => CHS ; ; Returns: ; ; ax => LBA ; ;********************; CHSLBA: sub ax, 0x0002 ; zero base cluster number xor cx, cx mov cl, BYTE [bpbSectorsPerCluster] ; convert byte to word mul cx add ax, WORD [datasector] ; base data sector ret ;********************; ; Convert LBA to CHS ; ; Parameters: ; ; ax => LBA ; ; Returns: ; ; ax => CHS ; ;********************; LBACHS: xor dx, dx ; prepare dx:ax for operation div WORD [bpbSectorsPerTrack] ; calculate inc dl ; adjust for sector 0 mov BYTE [absoluteSector], dl xor dx, dx ; prepare dx:ax for operation div WORD [bpbHeadsPerCylinder] ; calculate mov BYTE [absoluteHead], dl mov BYTE [absoluteTrack], al ret ;***********************************; ; Reads a series of sectors ; ; Parameters: ; ; cx => Number of sectors to read ; ; ax => Starting sector ; ; es:ebx => Buffer to read to ; ;***********************************; ReadSectors: pusha .start: mov di, 0x0005 ; five retries for error .sectorloop: call LBACHS ; convert starting sector to CHS mov ah, 0x02 ; BIOS read sector mov al, 0x01 ; read one sector mov ch, BYTE [absoluteTrack] ; track mov cl, BYTE [absoluteSector] ; sector mov dh, BYTE [absoluteHead] ; head mov dl, BYTE [bootDrive] ; drive int 0x13 ; invoke BIOS jnc .success ; test for read error xor ax, ax ; BIOS reset disk int 0x13 ; invoke BIOS dec di ; decrement error counter jnz .sectorloop ; attempt to read again .success: push cx ; queue next segment mov cx, WORD [bpbBytesPerSector] shr cx, 4 mov dx, es add dx, cx mov es, dx pop cx inc ax ; queue next sector loop .start ; read next sector popa ret ;************************; ; Parameters: ; ; si => string pointer ; ;************************; BiosPrint: pusha .loop: lodsb or al, al jz .done mov ah, 0x0E int 0x10 jmp .loop .done: popa ret Message.Error.NoBootablePartition db "No bootable partition found.", 13, 10, 0 Message.cazzo db "CAZZO", 13, 10, 0 bootDrive db 0 ; Our Drive Number Variable PToff dw 0 ; Our Partition Table Entry Offset times (0x1b4 - ($-$$)) nop ; Pad For MBR Partition Table UID times 10 db 0 ; Unique Disk ID PT1 times 16 db 0 ; First Partition Entry PT2 times 16 db 0 ; Second Partition Entry PT3 times 16 db 0 ; Third Partition Entry PT4 times 16 db 0 ; Fourth Partition Entry dw 0xAA55 ; Boot Signature |
Author: | PeterX [ Sun Nov 01, 2020 12:25 pm ] |
Post subject: | Re: Making a bootable image |
I don't know if this is the reason, but it is wrong: Code: int 0x13 ; invoke BIOS jnc .success ; test for read error xor ax, ax ; BIOS reset disk int 0x13 ; invoke BIOS dec di ; decrement error counter jnz .sectorloop ; attempt to read again .success: This means, it counts down (via DI) and if it still fails, it continues with success. There should be some error output and halt between "jnz .sectorloop" and ".success" Also I have the impression you take too advanced code. You kind of copy code from somewhere without truely understanding it. It would be better for your coding success if you try something "smaller" first. For example you can assume that partition bootsector is at sector 2048 (because FDISK does so). This is not good for a real OS, but you can concentrate more on the disk read subroutine. Have you looked at Ralph Brown's Interrupt List for disk read routines? Greetings Peter |
Author: | BenLunt [ Sun Nov 01, 2020 1:15 pm ] |
Post subject: | Re: Making a bootable image |
PeterX wrote: Also I have the impression you take too advanced code. You kind of copy code from somewhere without truly understanding it. I am going to agree with Peter here. The FAT file system occupies certain parts of the partition. This is a must. Therefore, you *must* preserve these areas when writing boot code to the partition. The first sector of the partition, sometimes called a Logical Sector Number of zero, must contain a valid BPB for the FAT type it uses. The FAT-12 and FAT-16 use the same data region, while FAT-32 occupies a little more of the first sector. As long as you preserve these areas, you are free to add code to the rest. Please note that the utility that is writing the code to LSN 0 will already know if it is a FAT-12, -16, or -32 file system and will act accordingly. For FAT-12 and -16 file systems, as long as you use a short jump plus a NOP as the first three bytes of LSN 0, and skip over the BPB, you can use the remaining part of the sector as code, minus the last two bytes, which must be the 0xAA55 signature. In fact, the FAT-12 and -16 file systems allow you to use additional sectors for code starting at LSN 1. However, since the MBR code only loaded 1 sector, your code within the LSN 0 *must* load any remaining sectors to memory. For FAT-32, LSN 1 through x are used for the file system and must be preserved. This includes a INFO sector. However, with all three types, as long as you preserved these areas, you can have many sectors worth of code for your boot code. As with Peter's suggestion, I suggest that you study how the FAT file system works *before* you try to write boot code for it. As for the code you posted, it makes a lot of assumptions that a newbie will completely miss. One huge example will be the ORG 0x0600 line. Yes, this is correct, given the code doesn't make any memory references until after it moves to 0x00600, but a quick glance over and one might assume too much about this assumption. Ben - http://www.fysnet.net/osdesign_book_series.htm |
Author: | bzt [ Sun Nov 01, 2020 1:42 pm ] |
Post subject: | Re: Making a bootable image |
Bonfra wrote: It prints "Hello, World!" but if i boot the disk.dd it prints nothing, instead it clears the screen (which I think is not a good thing). PeterX and BenLunt gave good advice. However I would also recommend to try it with a known to work MBR code first, before you write your own MBR code.Is it something with the disk reading part? This is the code for the MBR Under Windows, just use "FDISK.EXE /MBR". Under Linux, use "ms-sys --mbrdos". The code for this MBR sector can be found here (sadly just a byte array), but there's a detailed disassembly with fully commented source code here. In theory the MBR code does nothing else than chainloading the VBR sector to 0:7C00h. If your image works with the standard code, then the problem is with your MBR code. If it still doesn't work, then the problem is with your disk image creation. FYI this site also contains all MS boot sectors (MBR and VBR alike). You can find a FAT boot sector for floppies as well as for exFAT disks. Cheers, bzt |
Author: | Bonfra [ Mon Nov 02, 2020 2:28 am ] |
Post subject: | Re: Making a bootable image |
Yea you are right, I should start easy implementing my own stuffs. I tried implementing this ReadSector function: Code: ReadSectors: mov bx, 0x7C00 ; address mov al, 1 ; Number of Sectors mov dl, [bootDrive] mov ch, 0x00 ; cylinder 0 mov dh, 0x20 ; head 0 mov cl, 0x21 ; disk sector number mov ah, 0x02 int 0x13 ; Invoke BIOS ret Which relies on this datas: But the carry flag is setted by the BIOS function so it fails and I don't understand the reason |
Page 3 of 7 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |