; $Id: bootsec.asm,v 1.6 2002/04/25 21:00:41 reddawg Exp $ %include "gdtnasm.inc" [ORG 0x7c00] jmp start nop id db 'UbixFS' ;file system id version dd 1h ; Filing System Version fs_start dd 101 ; LBA address for start of root dir krnl_size dd 59 ; Kernel size in sectors, starts at sector 1 BytesPerSector dw 512 SectorsPerTrack dw 18 TotalHeads dw 2 TotalSectors dd 2880 ; 1474560/512 for a 1.44meg disk file_entry_nextdata equ 273 ; Offset in file_entry structure to the nextdata LBA pointer data_entry_data equ 9 ; Offset in data_entry structure to the data bootdrv db 0 start: xor ax, ax mov ds, ax mov [bootdrv], dl ;mov al,0x13 ;int 0x10 ; First get into protected mode cli n5: in al, 0x64 ;Enable A20 {4A} {5} test al, 2 jnz n5 mov al, 0xD1 out 0x64, al n6: in al, 0x64 test al, 2 jnz n6 mov al, 0xDF out 0x60, al lgdt [gdtinfo] ;Load GDT mov ecx, CR0 ;Switch to protected mode inc cx mov CR0, ecx mov ax, flat_data-gdt_table ; Selector for 4Gb data seg mov ds, ax ; {2} Extend limit for ds mov es, ax ; Extend limit for es mov fs, ax ; fs and... mov gs, ax ; gs dec cx ; switch back to real mode mov CR0, ecx sti xor ax, ax mov ds, ax mov dl, [bootdrv] mov bx, 0x60 mov es, bx mov eax, 1 mov ecx, [krnl_size] mov di, 1 load_loop: call read_sectors inc eax mov bx, es add bx, 32 mov es, bx loop load_loop ; Turn off the floppy motor, its annoying leaving it on ! mov edx,0x3f2 mov al,0x0c out dx,al ;lets convert the ELF file to a linear binary so we can execute it cmp dword [0x600],464c457fh ; The ELF signature is \07fELF jne ldr_ELF_err ; Ugh... not an ELF file !!! cmp word [0x600+4],101h ; It should be statically linked etc. jne ldr_ELF_err cmp byte [0x600+6],1 jne ldr_ELF_err jmp short skip_err_handler ldr_ELF_err: mov ax, 'E'+0x0E00 mov bx, 7 int 10h mov al, 'L' int 10h mov al, 'F' int 10h cli hlt skip_err_handler: mov eax, [0x600+18h] mov [krnl_entry], eax xor ecx,ecx ; Get the number of sections in cx mov cx,[0x600+2ch] sectionloop: dec cx ; Next section push cx ; Save cx on the stack while we load ; the section into memory mov eax,[0x600+2ah] ; Get the program header entry size mul cx ; Calculate the offset from the start ; of the program header table mov ebx,[0x600+1ch] ; Get the PHT offset in ebx add ebx,eax ; Add it to our PHT entry offset add ebx,0x600 ; Calculate the address of the entry cmp dword [bx],1 ; Does this section have to be ; loaded into memory ? jne nextsect ; No, next section mov dword ecx,[bx+4h] ; Get the offset of the segment in ; the ELF file mov dword ebp,[bx+10h] ; Get the size of the segment in the ; ELF file mov dword edi,[bx+8h] ; Get the memory address of the sect. mov dword eax,[bx+14h] ; Get the size of the section in mov ebx,eax ; the memory into ebx ; ds:dx = Address of ASCIIZ filename ; es:edi = Where in memory to put it ; ecx = Offset in file to start reading (bytes) ; ebp = Length of segment to read (bytes) ; ; Returns: ; eax = Length of file that was loaded ; eax = 0 if an error occured push ebp pusha mov esi, 0x600 add esi, ecx mov ecx, ebp call memcopy popa pop eax sub ebx,eax ; This amount needs to be zeroed jz nextsect ; It's ok, next section add edi,eax ; Zero the memory from this address xor ax,ax ; edi is an absolute address mov ecx,ebx call zero_memblock ; Zero the rest of the section nextsect: pop cx ; Restore our section count or cx,cx ; Was this the last one ? jnz sectionloop ; Re-enter protected mode ! A20 is already enabled cli ; No interrupts please at all lgdt [gdtinfo] mov ecx, cr0 inc cx mov cr0, ecx mov ax, flat_data-gdt_table mov ds, ax mov es, ax mov fs, ax mov gs, ax jmp dword (flat_code-gdt_table):pmode1 pmode1: [BITS 32] push dword 2 popfd mov eax, [krnl_entry] call eax cli hlt ;Hang the system.. hang: jmp hang [BITS 16] read_sectors: ; Input: ; EAX = LBN ; DI = sector count ; ES = segment ; Output: ; BL = low byte of ES ; EBX high half cleared ; DL = 0x80 ; EDX high half cleared ; ESI = 0 pusha cdq ;edx = 0 movzx ebx, byte [SectorsPerTrack] div ebx ;EAX=track ;EDX=sector-1 mov cx, dx ;CL=sector-1 ;CH=0 inc cx ;CL=Sector number xor dx, dx mov bl, [TotalHeads] div ebx mov dh, dl ;Head mov dl, [bootdrv] ;Drive 0 xchg ch, al ;CH=Low 8 bits of cylinder number; AL=0 shr ax, 2 ;AL[6:7]=High two bits of cylinder; AH=0 or cl, al ;CX = Cylinder and sector mov ax, di ;AX = Maximum sectors to xfer retry: mov ah, 2 ;Read xor bx, bx int 13h jc retry popa ret ; zero_memblock: Fills the specified memory block with zeros (0x0) ; ; Takes parameters: ; ax = segment/selector of memory to be cleared ; edi = offset of memory to be cleared ; ecx = number of bytes to clear ; ; Returns: ; nothing zero_memblock: push eax ; Save the registers push edi push ecx push es mov es,ax xor eax,eax ; Fill the memory with zeros (0x0) cld ; Clear the direction flag; rep increments di a32 rep stosb ; Fill the memory (one byte at a time) pop es ; Restore the registers pop ecx pop edi pop eax ret ; Return to the main program ; Parameters ; DS:ESI = Source ; DS:EDI = Destination ; CX = length memcopy: pusha memcopy_loop: mov al, [esi] mov [edi], al inc edi inc esi loop memcopy_loop popa ret print: lodsb ; load next character or al, al ; test for NUL character jz .DONE mov ah, 0x0E ; BIOS teletype mov bh, 0x00 ; display page 0 mov bl, 0x07 ; text attribute int 0x10 ; invoke BIOS jmp print .DONE: ret gdtinfo: dw gdtlength dd gdt_table ;********* GDT TABLE gdt_table: null_desc desc 0,0,0 flat_code desc 0, 0xFFFFF, D_CODE + D_READ + D_BIG + D_BIG_LIM flat_data desc 0, 0xFFFFF, D_DATA + D_WRITE + D_BIG + D_BIG_LIM gdtlength equ $ - gdt_table - 1 ;********* END GDT TABLE krnl_entry dd 0 bootMsg db 'Loading UbixOS' , 0x0D, 0x0A, 0x00 times 510-($-$$) db 0 dw 0xAA55