OS loader

Odpowiedz Nowy wątek
2004-12-19 12:05

Rejestracja: 16 lat temu

Ostatnio: 1 rok temu

Lokalizacja: Gorlice/Kraków

0

Mam problem. Napisałem sobie taki prosty OS loader, który ma zaladować 32-bitowy kernel, wejść w PMODE i skoczyć do niego. Oto jego kod:

; INIT MILYGES OS

InitAdress      EQU 0x800
InitSegment     EQU 0x80
KernelAdress        EQU 0x19000
KernelSegment       EQU 0x9000

RootDirOffset       EQU 0xC800  
FATOffset       EQU 0x7800  

%macro prologue 1 
    push ebp 
    push bp
    mov ebp,esp 
    sub esp,%1 
%endmacro 
%macro epilogue 0
    mov esp,ebp 
    pop bp
    pop ebp 
%endmacro 
%macro MoveData 5
    push dword %1
    push dword %2
    push dword %3
    push dword %4
    push dword %5
    call _MoveData
    add esp, 20
%endmacro 
%macro Mul16EAX 1
    push edx
    mul %1
    xchg eax,edx        ; now moving the MSB in dx to eax
    shl eax,16
    mov ax,dx
    pop edx
%endm
%macro Mul32EAX 1
    push edx
    mul %1
    xchg eax,edx        ; now moving the MSB in dx to eax
    shl eax,16
    mov ax,dx
    pop edx
%endm
;input Dividend , divisor
;output : quotient - ax , modulo - dx
%macro Div32EAX 2
    push ecx

    mov eax, %1
    mov edx, %1
    shr edx, 16
    mov ecx, %2
    div cx

    pop ecx
%endm

; INIT CODE
[BITS 16]
[ORG 0x0000]

jmp main16

[BITS 32]

[SECTION .data] ;32-bit data

;=====================================================
;Global Descriptor Table 
;=====================================================
gdt_descr: 
dw 256*8-1
dd _gdt

GLOBAL _gdt
_gdt:
dd 0,0
dd 0x0000FFFF,0x00CF9A00
dd 0x0000FFFF,0x00CF9200
dd 0,0
times 254 dd 0,0 

;=====================================================
;Interrupt Descriptor Table
;=====================================================
idt_descr: 
dw 256*8-1
dd _idt

GLOBAL _idt
_idt:
 times 256 dd 0,0

[BITS 16]
main16:
    CLI
    MOV AX, InitSegment
    MOV DS, AX
    MOV ES, AX
    MOV FS, AX
    MOV GS, AX

    ; Create stack
    MOV AX, 0x0000
    MOV SS, AX
    MOV SP, 0xFFFF

    ;loading orig boot parameters from 0x7C00
    push ds
    mov cx,62
    mov ax,7c0h
    mov ds,ax
    mov di,OEM_ID
    mov si,3
    cld
    rep movsb
    pop ds

    STI

    MOV BX, msg_intro
    CALL print

    MOV BX, msg_linea20
    CALL print

    CALL setup_a20

    MOV BX, msg_ok
    CALL print

xor eax, eax
    mov al, byte [SectorsPerCluster]         ;size of cluster
    Mul16EAX word [BytesPerSector]
    mov word [BytesPerCluster], ax

    MOV BX, msg_loading
    CALL print
;=======================================================================
;LOAD KERNEL TO MEMORY
;=======================================================================

LOAD_ROOT:
    ;compute size of root directory and store in ?cx?
    xor cx, cx
    xor dx, dx
    mov ax, 0x0020                          ; 32 byte directory entry
    mul WORD [MaxRootEntries]               ; total size of directory
    div WORD [BytesPerSector]               ; sectors used by directory
    xchg ax, cx
    ;compute location of root directory and store in ?ax?
    mov al, BYTE [TotalFATs]                ; number of FATs
    mul WORD [SectorsPerFAT]                ; sectors used by FATs
    add ax, WORD [ReservedSectors]          ; adjust for bootsector
    mov WORD [datasector], ax               ; base of root directory
    add WORD [datasector], cx

    ;read root directory into memory 
    mov bx, RootDirOffset           ; copy root dir above code
    call ReadSectors

    ;browse root directory for binary image
    mov cx, WORD [MaxRootEntries]           ; load loop counter
    mov di, RootDirOffset               ; locate first root entry
.LOOP:
    push cx
    push di

    mov cx, 0x000B                          ; eleven character name
    mov si, ImageName                       ; image name to find

    rep cmpsb                               ; test for entry match

    pop di
    pop cx

    je LOAD_FAT

    add di, 0x0020                          ; queue next directory entry
    loop .LOOP
    jmp     FAILURE

LOAD_FAT:

    mov eax, dword [di + 0x001c]             ; file size
    mov [FileSize], eax

    mov dx, WORD [di + 0x001A]
    mov WORD [cluster], dx                  ; file?s first cluster
    ;compute size of FAT and store in ?cx?
    xor ax, ax
    mov al, BYTE [TotalFATs]                ; number of FATs
    mul WORD [SectorsPerFAT]                ; sectors used by FATs
    mov cx, ax
    ;compute location of FAT and store in ?ax?
    mov ax, WORD [ReservedSectors]          ; adjust for bootsector
    ;read FAT into memory 
    mov bx, FATOffset                ; copy FAT above bootcode
    call ReadSectors

    ;------------------Reading Kernel DLL into memory------------------
    mov ax, KernelSegment               ; destination of image CS
    mov es, ax
    mov bx, 0x0000                          ; destination for image IP
    push bx
    mov byte [ShowProgress],1
LOAD_IMAGE:
    mov ax, WORD [cluster]                  ; cluster to read
    pop bx                                  ; buffer to read into
    call ClusterLBA                         ; convert cluster to LBA
    xor cx, cx
    mov cl, BYTE [SectorsPerCluster]        ; sectors to read
    call ReadSectors

    cmp bx, 1024                ; Segment override (64kb)
    jne .SegmentOk
    mov ax, es                  ; next segment ( add 64)
    add ax, 64
    mov es, ax
    mov bx, 0
.SegmentOk:

    push    bx                  ;compute next cluster
    mov ax, WORD [cluster]                  ; identify current cluster
    mov cx, ax                              ; copy current cluster
    mov dx, ax                              ; copy current cluster
    shr dx, 0x0001                          ;
    ;divide by two
    add cx, dx                              ; sum for (3/2)
    mov bx, FATOffset               ; location of FAT in memory
    add bx, cx                              ; index into FAT
    mov dx, WORD [bx]                       ; read two bytes from FAT
    test ax, 0x0001
    jnz .ODD_CLUSTER
.EVEN_CLUSTER:
    and dx, 0000111111111111b               ; take low twelve bits
    jmp .DONE
.ODD_CLUSTER:
    shr dx, 0x0004                          ; take high twelve bits
.DONE:
    mov WORD [cluster], dx                  ; store new cluster
    cmp dx, 0x0FF0                          ; test for end of file
    jb LOAD_IMAGE

JMP DONE

;ON ERROR
FAILURE:
    MOV BX, msg_error
    CALL print
    MOV BX, msg_reboot
    CALL print
    MOV AX, 10H
    INT 16H
    INT 19H

;=======================================================================
;Exec Kernel
;=======================================================================    
DONE:
    MOV BX, msg_ok
    CALL print

    MOV BX, msg_gdt
    CALL print

    LGDT [gdt_descr]

    MOV BX, msg_ok
    CALL print

    MOV BX, msg_idt
    CALL print

    MOV BX, msg_ok
    CALL print

    CLI

    LIDT [idt_descr]

    MOV EAX, CR0
    OR EAX, 1
    MOV CR0, EAX

    PUSH 0x0000
    PUSH dword KernelAdress

    RETF

;===============================================================
; PROCEDURES
;===============================================================
;*************************************************************************
; PROCEDURE ReadSectors
; reads ?cx? sectors from disk starting at ?ax? into
;memory location ?es:bx?
;*************************************************************************
ReadSectors:
.MAIN:
    mov     di, 0x0005                          ; five retries for error
.SECTORLOOP:
    push    ax
    push    bx
    push    cx
    call    LBACHS
    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 [DriveNumber]              ; 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
    pop     cx
    pop     bx
    pop     ax
    jnz     .SECTORLOOP                         ; attempt to read again
    int     0x18
.SUCCESS:
    cmp byte [ShowProgress],0
    je .PROGRESSDONE
    mov bx, msg_process
    call print

    .PROGRESSDONE:
    pop     cx
    pop     bx
    pop     ax
    add bx, WORD [BytesPerSector]           ; queue next buffer
    inc     ax                                  ; queue next sector
loop    .MAIN                               ; read next sector
    ret
;
;
;
; PutI2- Recursive routine to actually print the value in AX as an integer.
;
Puti2:
    push dx

    mov bx, 10
    xor dx, dx
    div bx
    or  ax, ax      ;See if ax=0
    jz  .Done
    push dx
    call Puti2
    pop dx
.Done:  
    mov al, dl
    or  al, '0'
    mov byte [si], al
    inc si

    pop dx
    ret

;*************************************************************************
; PROCEDURE ClusterLBA
; convert FAT cluster into LBA addressing scheme
; LBA = (cluster - 2) * sectors per cluster
;*************************************************************************
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

;*************************************************************************
; PROCEDURE LBACHS
; convert ?ax? LBA addressing scheme to CHS addressing scheme
; absolute sector = (logical sector / sectors per track) + 1
; absolute head   = (logical sector / sectors per track) MOD number of heads
; absolute track  = logical sector / (sectors per track * number of heads)
;*************************************************************************
LBACHS:
    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 [NumHeads]                     ; calculate
    mov     BYTE [absoluteHead], dl
    mov     BYTE [absoluteTrack], al
    ret

;*************************************************************************
;print TEXT
print: ;BX - pointer to text
    PUSH AX
    PUSH BX
    PUSH CX
    PUSH DX
    MOV AH, 0x0E

print_loop:
    MOV AL, [BX]
    CMP AL, 0x00
    JE print_end
    INC BX
    PUSH BX
    MOV BH, 0x00
    MOV BL, 0x07
    INT 10H
    POP BX
    JMP print_loop

print_end:
    POP DX
    POP CX
    POP BX
    POP AX
    RET

;UNLOCK A20 LINE
setup_a20:
    CALL empty_8042
    MOV AL, 0xD1
    OUT 0x64, AL
    CALL empty_8042
    MOV AL, 0xDF
    OUT 0x60, AL
    CALL empty_8042
    JMP setup_a20_end
empty_8042:
    DW 0xEB, 0xEB
    IN AL, 0x64
    TEST AL, 2
    JNZ empty_8042
    RET
setup_a20_end:
    RET

;16-BIT DATA

    absoluteSector db 0x00
    absoluteHead   db 0x00
    absoluteTrack  db 0x00

    datasector      dw 0x0000
    cluster         dw 0x0000
    ImageName       db "KERNEL  SYS"

msg_intro           db 10,13,"MILYGES OS INIT v1.0",10,13,0
msg_linea20         db "Unloking line A20..........",0
msg_loading         db "Loading kernel",0
msg_gdt         db "Loading GDT................",0
msg_idt         db "Loading IDT................",0
msg_execkernel      db "Starting kernel............",10,13,0
msg_ok          db "OK",10,13,0
msg_error           db "ERROR",10,13,0
msg_reboot          db 10,13,10,13,"Press any key to reboot...",10,13,0
msg_process         db ".",0

    ShowProgress    db 1
    FileSize            dd 0
    ReadFileSize        dd 0

    BytesPerCluster     dw 0

    Buffer              db "    ",0

    OEM_ID        db "MILYGES "
    BytesPerSector        dw 0x0200
    SectorsPerCluster     db 0x01
    ReservedSectors       dw 0x0001
    TotalFATs             db 0x02
    MaxRootEntries        dw 0x00E0
    TotalSectorsSmall     dw 0x0B40
    MediaDescriptor       db 0xF0
    SectorsPerFAT         dw 0x0009
    SectorsPerTrack       dw 0x0012
    NumHeads              dw 0x0002
    HiddenSectors         dd 0x00000000
    TotalSectorsLarge     dd 0x00000000
    DriveNumber           db 0x00
    Flags                 db 0x00
    Signature             db 0x29
    VolumeID              dd 0xFFFFFFFF
    VolumeLabel           db "MILYGES OS "
    SystemID              db "FAT12   "

Moje pytanie brzmi: Dlaczego podczas skoku do punkty wejścia kernela komputer się restartuje????


Pozostało 580 znaków

2004-12-19 21:37

Rejestracja: 17 lat temu

Ostatnio: 1 miesiąc temu

0

pewnie jak to zwykle bywa skacze nie tam gdzie powinien... zrob tak aby kod byl ladowany w pierwszy segment 16bit dzieki czemu adresy logiczny i fizyczny beda takie same, to powinno zadzialac wtedy :P


Pozostało 580 znaków

milyges
2004-12-20 13:02
milyges
0

A jeśli mój kernel ma więcej niż jeden segment w pamięci. Te loadery, które widziałem, nie ładują plików, których rozmiar jest widziałe, nie ładują pkików większych niż ok 2KB. Mój kernel ma 7KB. Co wtedy???

Pozostało 580 znaków

2004-12-21 15:30

Rejestracja: 17 lat temu

Ostatnio: 1 miesiąc temu

0

hmm no to sprawa sie komplikuje... ja bym zrobil tak:
w asmie napisal fisrt stage loader czyli zwyklego boota ktory ładuje tzw: second stage loader czyli program ktory moze byc troche wieksszy i laduje on dopiero kernel, mozna by go s<ort>prubowac</ort> napisac w c..

PS. nie wiem skund ci sie wzielo 2kb jak funkcje biosa moga spokojnie zaladowac pojedynczy plik do segmentu o dlugosci 64kb...


Pozostało 580 znaków

2005-01-03 11:41

Rejestracja: 16 lat temu

Ostatnio: 1 rok temu

Lokalizacja: Gorlice/Kraków

0

Dzięki wszystkim. Już działa. nie długo do porbrania z <url>www.milyges.prv.pl</url&gt;


Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0