;=----------------------------------------------------------------------------=; ; GNU GPL OS/K ; ; ; ; Authors: spectral` ; ; NeoX ; ; ; ; Desc: Master Boot Record for OS/K ; ; (x86_64 architecture only) ; ;=----------------------------------------------------------------------------=; %define SECOND_STAGE 0x100 [BITS 16] ; real mode [ORG 0x7C00] ; address where the BIOS/UEFI CSM is loading us jmp short Start ;; File Allocation Table Disk Identifiers nop OEM_ID db "GPL OS/K" BytesPerSector dw 0x0200 SectorsPerCluster db 0x08 ReservedSectors dw 0x0020 TotalFATs db 0x02 MaxRootEntries dw 0x0000 NumberOfSectors dw 0x0000 MediaDescriptor db 0xF8 SectorsPerFAT dw 0x0000 SectorsPerTrack dw 0x003D SectorsPerHead dw 0x0002 HiddenSectors dd 0x00000000 TotalSectors dd 0x00FE3B1F BigSectorsPerFAT dd 0x00000778 Flags dw 0x0000 FSVersion dw 0x0000 RootDirectoryStart dd 0x00000002 FSInfoSector dw 0x0001 BackupBootSector dw 0x0006 TIMES 12 DB 0 ; going to the next offset DriveNumber db 0x00 ReservedByte db 0x00 Signature db 0x29 VolumeID dd 0xFFFFFFFF VolumeLabel db "OS/K BDISK " SystemID db "FAT32 " Start: ;; saving registers for future pushad pushfd pushf ;; dl contains the boot drive. Saving it. mov [Bootdrv], dl ;; hello world push si mov si, Starting call PrintB ;; SWITCHING TO LOADER mov si, Switch call PrintB pop si mov cx, word [SectorsPerCluster] ; size of a cluster in sectors is stored in cx ; computing location of the begining of the Data area and store in ax mov al, byte [TotalFATs] ; Total number of FATs mul word [BigSectorsPerFAT] ; Number of sectors for a FAT add ax, word [ReservedSectors] ; Find the start of the Data area mov word [Datasector], ax ; Store the begining of the Data area ; reading 1st data cluster into memory (7C00:0200) mov ax, word [RootDirectoryStart] call ClusterLBA mov bx, 0x0200 ; copy 1st data cluter above bootcode call ReadSectors ; Point Index register to 1st File Entry mov di, 0x0200 + 0x20 ;Point to the offset where the file location information contains mov dx, word [di + 0x001A] mov word [Cluster], dx ;Set up the segments where the loader needs to be loaded ;) mov ax, 0100h ; set ES:BX = 0100:0000 mov es, ax xor bx, bx ;Read the cluster which contains the loader mov cx, 0x0008 mov ax, word [Cluster] call ClusterLBA call ReadSectors ;Jump to the location where the loader was loded popf popfd popad push word [Bootdrv] call dword SECOND_STAGE:0000 ; Exiting mov ah, 0x00 int 0x19 ; warm boot computer ;;END OF MBR ;;----------------------------------------------------------------------------;; ;; DATA Starting db 0x0A, 0x0D, 0x07, "GNU GPL OS/K", 0x0A, 0x0D, 0x0A, 0x0D, 0 Switch db 0x09, " Loading Second Stage", 0 AbsoluteSector db 0x00 AbsoluteHead db 0x00 AbsoluteTrack db 0x00 Cluster dw 0x0000 Datasector dw 0x0000 Bootdrv db 0x00 ;; INCLUDES %include "boot/common.inc" ; for PrintB ;; INTERNAL FUNCTIONS ;-------------------------------------------------------------------; ; loading second stage loader (loader.s) ; ;-------------------------------------------------------------------; ReadSectors: .main: mov di, 0x0005 ; five retries for error .sectorloop: push ax push bx push cx call LbaToChs 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 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 pop cx pop bx pop ax jnz .sectorloop ; attempt to read again int 0x18 .success: pop cx pop bx pop ax add bx, WORD [BytesPerSector] ; queue next buffer inc ax ; queue next sector loop .main ; read next sector ret ;-------------------------------------------------------------------; ; Converts LBA Adresses to CHS ; ;-------------------------------------------------------------------; LbaToChs: xor dx, dx ; prepare dx:ax for operation div WORD [SectorsPerTrack] ; calculate inc dl ; adjust for sector 0 mov BYTE [AbsoluteSector], dl xor dx, dx ; prepare dx:ax for operation div WORD [SectorsPerHead] ; calculate mov BYTE [AbsoluteHead], dl mov BYTE [AbsoluteTrack], al ret ;-------------------------------------------------------------------; ; Converts FAT Adresses to LBA ; ;-------------------------------------------------------------------; ClusterLBA: sub ax, 0x0002 ; zero base cluster number xor cx, cx mov cl, BYTE [SectorsPerCluster] ; convert byte to word mul cx add ax, WORD [Datasector] ; base data sector ret End: times 510-($-$$) db 144 ; NOP until 510 dw 0xAA55 ; magic word