loader

loader 做的事情比较单一,将ELF文件直接复制到指定内存区(在实模式下,地址区内存 <= 1M)




    org    0100h
    jmp     _loader_start            ; Start to load kernel module.

    %include "fat.inc"
    %include "pmhdr.inc"

    BaseOfLoader    equ    09D00h        ;
    OffsetOfLoader    equ    0100h        ; 0x9d000 - 0x9fc00 for loader.bin

    KernelEntry        equ    115000h     ; 1M + 84K for kernel space
    kernel_size     equ 0D000h      ; 128 KB for kernel

    BaseOfKernel    equ    07D00h        ;
    OffsetOfKernel    equ    0            ; 0x7d000 - 0x9d000 for kernel.bin

    base_of_fs      equ 05d00h      ; 0x5d000 - 0x7d000 for fs.bin
    off_fs          equ 0

    base_of_tty     equ 03d00h      ; 0x3d000 - 0x5d000 for tty.bin
    off_tty         equ 0
    
    base_of_mm      equ 01d00h      ; 0x1d000 - 0x3d000 for mm.bin
    off_mm          equ 0

    base_of_shell   equ 0d00h       ; 0x0d000 - 0x1d000 64 KB for shell.bin
    off_shell       equ 0

    base_of_tst     equ 0100h       ; 0x1000 - 0xd000 for tst.bin
    off_tst         equ 0      

    FATTabBase        equ    50h         ; FAT tab Base
    FATTabOffset    equ    0h            ; FAT tab Offset
    FATTabLen       equ 0x1200      ; FAT tab length (total 4.5KB)

    page_dir_table    equ    100000h        ; page_dir_table from 1M
    page_table      equ 101000h     ; 1M + 4K

    GDT:            Descriptor    0        ,    0        ,   0
    FLAT_C:            Descriptor    0        ,   0FFFFFH    ,    DA_CR |DA_32|DA_LIMIT_4K    ; 0~4G code
    FLAT_RW            Descriptor    0        ,    0FFFFFH    ,    DA_DRW|DA_32|DA_LIMIT_4K    ; 0~4G data
    VIDEO:            Descriptor    0B8000H ,    0FFFFH    ,    DA_DRW|DA_32|DA_DPL3


    GdtLen            equ    $ - GDT
    GdtPtr            dw    GdtLen - 1  ; GdtLimit
                    dd    BaseOfLoader * 16 + GDT

    ;selector
    SelectorFlat_C    equ    FLAT_C - GDT; 8h
    SelectorFlat_RW    equ    FLAT_RW- GDT; 10h
    SelectorVideo    equ    VIDEO  - GDT; 18h
    

    ;VAR IN REAL MODEL
    RootTotalSects    equ    14            ; Root Sects
    SrchFromSect    dw    19            ; search from SrchSectNum
    ;src

    ;   string source name
    src_name        db    "KERNEL  BIN"
                      db    "FSMAIN  BIN"
                    db  "TERMIO  BIN"
                    db  "MM      BIN"
                    db  "SHELL   BIN"
                    db  "BIN     BIN"

    ;   message string
    not_found        db    "PANIC !==> NO  "
    not_found_len   equ $ - not_found
    loading         db  "Loading "
    loading_len     equ $ - loading
    load_ok         db  " Loaded OK !"
    load_ok_len     equ $ - load_ok

    pt                dw    ((80 * 2 + 0) * 2)
    ;var ends
;
; code16 start
;

_loader_start:
    mov        ax,cs
    mov        ds,ax
    mov        es,ax

    mov        ss,ax
    mov        sp,0100h

    mov        ebx, 0
    mov        di, _MemChkBuf
.loop:
    mov        eax, 0E820h
    mov        ecx, 20
    mov        edx, 0534D4150h
    int        15h
    jc        MEM_CHK_FAIL
    add        di, 20
    inc        dword [_dwMCRNumber]
    cmp        ebx, 0
    jne        .loop
    jmp        MEM_CHK_OK
MEM_CHK_FAIL:
    mov        dword [_dwMCRNumber], 0
MEM_CHK_OK:
    xor        ah,ah
    xor        dl,dl
    int        13h                        ; RST floppy motor

    push    0
    push    OffsetOfKernel
    push    BaseOfKernel
    call    load
    add     sp,6

    push    1
    push    off_fs
    push    base_of_fs
    call    load
    add     sp,6

    push    2
    push    off_tty
    push    base_of_tty
    call    load
    add     sp,6

    push    3
    push    off_mm
    push    base_of_mm
    call    load
    add     sp,6

    push    4
    push    off_shell
    push    base_of_shell
    call    load
    add     sp,6

    push    5
    push    off_tst
    push    base_of_tst
    call    load
    add     sp,6

    call    KillMotor
    LGDT    [GdtPtr]
    cli

    ;open a20
    in        al,92H
    or        al,00000010B
    out        92H,al

    ;pe = 1
    mov        eax,CR0
    or        eax,1
    mov        CR0,eax

    mov     cx,word [pt]

    ; jmp to protect mode
    jmp        dword SelectorFlat_C:(BaseOfLoader * 16 + CODE32_START)
;----------------------------------------------------------------------------
; func: KillMotor ();
;----------------------------------------------------------------------------
KillMotor:
    push    dx
    mov        dx, 03F2h
    mov        al, 0
    out        dx, al
    pop        dx
    ret
; ============================================================================================
; void load ( unsigned short base ,unsigned short offset ,unsigned short src_index ) ;
; ============================================================================================
load:
    push    bp
    mov     bp,sp

    sub     sp,2                    ; local var for src str

    push    ax
    push    bx
    push    cx
    push    dx
    push    si
    push    di
    push    es

    mov     es,word [bp + 4]        ; get base
    mov     di,word [bp + 6]        ; get off
    mov     ax,word [bp + 8]        ; get index
    

    mov     si,src_name             
    mov     dl,11
    mul     dl
    add     si,ax                   ; get src string

    mov     word [bp - 2],si        ; store

    mov        cx,RootTotalSects       ; 14 sects..., 14 circles
.FindOutInRoot:
    push    cx                        ; cx(0)
    mov        bx,word [bp + 6]        ; get offset
    mov        ax,[SrchFromSect]       ; search from 19
    mov        cl,1                    ; begin to Read (cl) sects from Sects No.[SrchFromSect]
                                    ; to BaseOfLoader:OffsetOfLoader
    call    ReadSector
                                    ; Finish reading(total 512 bytes)
    cld
    mov        cx,10h                    ; 16 * 32 = 512 Bytes
.FindOutInSects:
    push    cx                        ; cx(1)
                                    ; 3rd cycle
    mov        cx,12
    call    __strncmp
    cmp     cx,0
    pop        cx                        ; cx(1)
    jz        .found                    ; if equal
    add        di,20h
    loop    .FindOutInSects            ; if not equal,find out in the next Dir Entry
    pop        cx                        ; cx(0)
    inc        word [SrchFromSect]
    loop    .FindOutInRoot
                                    ; if not found in this sect ,then next one sect
                                    ; if not found
    mov        si,not_found
    mov        cx,not_found_len
    call    dispstr

    mov     si,word [bp - 2]        ; show string
    mov     cx,11
    call    dispstr

    call    new_line

    jmp        $                        ; stop here

.found:
    pop        cx                        ; cx(0)

    mov        si,loading
    mov        cx,loading_len
    call    dispstr
    mov     si,word [bp - 2]
    mov     cx,11
    call    dispstr
    call    new_line

    ; if found,es:di --> Dest 32Bytes StartAddr
    ; We need to get the first sector
    add        di,01Ah                    ; [es:(di + 01ah)] -- > first cluser
    mov        ax,word [es:di]            ; ax -- > first cluser (FAT)
    mov        bx,word [bp + 6]

    mov        cl,1                    ; just one sector
    add        ax,31
.LoadFile:
    call    ReadSector                ; read a sect to BaseOfLoader:OffsetOfLoader
    push    ds
    push    si
    ;save ax
    push    ax
    mov        ax,FATTabBase
    mov        ds,ax
    mov        si,FATTabOffset
    pop        ax

    call    GetNextFAT
    ;restore
    pop        si
    pop        ds
    cmp        ax,0FFFH
    jz        .endload                ; if it is the last one,then quit
    add        ax,31                    ; if not find next FAT
    add        bx,512                    ; offset += 512
    jmp        .LoadFile                ; or else continue load file

.endload:                          ; from now on we finished loading kernel module
    mov     si,word [bp - 2]
    mov     cx,11
    call    dispstr

    mov        si,load_ok
    mov        cx,load_ok_len
    call    dispstr

    call    new_line

    pop     es
    pop     di
    pop     si
    pop     dx
    pop     cx
    pop     bx
    pop     ax

    mov     sp,bp
    pop     bp
    ret


    %include "rmlib.inc"


; now we entered the protected mode

[section .code32]
align 32
[bits 32]

CODE32_START:
    mov        ax,SelectorVideo
    mov        gs,ax

    mov        ax,SelectorFlat_RW
    mov        ds,ax
    mov        es,ax
    mov        fs,ax
    mov        ss,ax
    mov        esp,TopOfStack

    xor     ebx,ebx
    mov     bx,cx
    mov     dword [dwDispPos],ebx

    push    PMmsg
    call    DispStr
    add        esp,4

    PUSH    RamSize
    call    DispStr
    add        esp,4

    call    GetMemSize
    push    0x100000
    push    0
    push    0x100000
    call    memset
    add     esp,12
    call    SetupPaging

    push    PageMsg
    call    DispStr
    add        esp,4


    push    InitKernelStr
    call    DispStr
    add        esp,4

    call    InitKernel

    push    InitReady
    call    DispStr
    add        esp,4

    ; we gonna need some usefull info from real mode
    ; place them into regs is a good idear

    mov     eax,dword [dwMemSize]
    jmp        SelectorFlat_C:KernelEntry        ; we goto kernel

GetMemSize:
    mov        esi, MemChkBuf
    mov        ecx, [dwMCRNumber]              ; for(int i=0;i<[MCRNumber];i++)
.loop:                                        ; {
    push    ecx
    mov        ecx,5                            ;    for(int j=0;j<5;j++)
    mov        edi, ARDStruct                    ;    {
.1:                                            ;
    lodsd                                    ;
    stosd                                    ;        ARDStruct[j*4] = MemChkBuf[j*4];
    loop    .1                                ;    }
    pop        ecx                             ;
    mov        eax, [dwBaseAddrLow]            ;
    add        eax, [dwLengthLow]              ;
    cmp        eax, [dwMemSize]                ;    if(BaseAddrLow + LengthLow > MemSize)
    jb        .2                                ;    {
    mov        [dwMemSize], eax                ;            MemSize = BaseAddrLow + LengthLow
.2:                                            ;    }
    loop    .loop                            ; }
                                            ; /* the max mem_size for us is 64MB */
    cmp     dword [dwMemSize],0x4000000     ; if ( mem_size > 64 )
    jb      .less_512MB                     ;   mem_size = 64
    mov     dword [dwMemSize],0x4000000     ;
.less_512MB:                                ;
    push    dword [dwMemSize]               ;
    call    DispInt                            ; DispInt(MemSize);
    add        esp, 4                            ;
    ret

SetupPaging:
    mov        eax,dword [dwMemSize]
    shr     eax,12                          ; let it be 4KB alignment

    xor     edx,edx
    mov     ebx,1024                        ; let it be 4MB alignment
    div        ebx                             ; edx (ramin) eax (result)
    cmp     edx,0                           ; if 4MB alignment
    jz      .4MB_alignment
    add     eax,1                           ; if not ,add a page_dir_objs
.4MB_alignment:
    mov        ecx,eax

    mov        ax,SelectorFlat_RW
    mov        es,ax
    mov     ds,ax
    cld

    mov     edi,page_dir_table

    xor        eax,eax
    mov     eax,page_table | PG_P | PG_USU | PG_RWW
.1:
    stosd
    add        eax, 4096
    loop    .1

    ; page_table init...
    mov     ecx,dword [dwMemSize]
    shr     ecx,12                          ; 4KB alignment,(ecx) == how many pages we have
    mov     edi,page_table
    xor        eax, eax
    mov        eax, PG_P | PG_USU | PG_RWW
.2:
    stosd
    add        eax, 4096
    loop    .2
    ; start up paging....
    mov        eax, page_dir_table
    mov        cr3, eax
    mov        eax, cr0
    or        eax, 80000000h
    mov        cr0, eax
    ret

InitKernel:
    xor        esi,esi
    xor        ecx,ecx
    mov        cx,  word [BaseOfKernel * 16 + 02Ch]    ; e_phnum
    mov        esi,dword [BaseOfKernel * 16 + 1CH ]    ; e_phoff'
    add        esi,BaseOfKernel * 16                    ; e_phoff
_cpy:
    mov        eax,[esi + 0]                            ; if p_type == PT_NULL
    cmp        eax,0
    jz        _nextph

    mov        eax,dword [esi + 04H]                    ; p_offset'
    add        eax,BaseOfKernel * 16                    ; p_offset


    push    dword [esi + 010h]                        ; size
    push    eax                                        ; src offset
    push    dword [esi + 08h ]                        ; dest offset
    call    memcpy
    add        esp,12
_nextph:
    add        esi,32                                    ; next ph
    loop    _cpy

    ret

    %include "pmlib.inc"

    ;data sect
    [section .data32]
    align 32
    [bits 32]
    DATA32_START:

    ;msg
    _PMmsg:                    db    "Protect Mode Actived!",0ah,0
    _PageMsg:                db    0ah,"Paging Ready!",0AH,0
    _RamSize                db    "Total RAM Size:",0
    _InitKernelStr            db    "Inint Kernel...",0ah,0
    _InitReady                db    "Kernel Ready!",0ah,0
    ;var
    _dwMCRNumber:            dd    0                    ; Memory Check Result
    _dwDispPos:                dd    (80 * 8 + 0) * 2    ;
    _dwMemSize:                dd    0
    _ARDStruct:                                        ; Address Range Descriptor Structure
        _dwBaseAddrLow:        dd    0
        _dwBaseAddrHigh:    dd    0
        _dwLengthLow:        dd    0
        _dwLengthHigh:        dd    0
        _dwType:            dd    0

    _MemChkBuf:    times 1024    db    0

    PMmsg                    equ    _PMmsg            + BaseOfLoader * 16
    PageMsg                    equ    _PageMsg        + BaseOfLoader * 16
    RamSize                    equ    _RamSize        + BaseOfLoader * 16
    InitKernelStr            equ    _InitKernelStr    + BaseOfLoader * 16
    InitReady                equ    _InitReady        + BaseOfLoader * 16
    ;
    dwMCRNumber                equ    _dwMCRNumber    + BaseOfLoader * 16
    dwDispPos                equ    _dwDispPos        + BaseOfLoader * 16
    dwMemSize                equ    _dwMemSize        + BaseOfLoader * 16
    ARDStruct                equ    _ARDStruct        + BaseOfLoader * 16
        dwBaseAddrLow        equ    _dwBaseAddrLow    + BaseOfLoader * 16
        dwBaseAddrHigh        equ    _dwBaseAddrHigh    + BaseOfLoader * 16
        dwLengthLow            equ    _dwLengthLow    + BaseOfLoader * 16
        dwLengthHigh        equ    _dwLengthHigh    + BaseOfLoader * 16
        dwType                equ    _dwType            + BaseOfLoader * 16
    MemChkBuf                equ    _MemChkBuf        + BaseOfLoader * 16

    StackSpace:    times 1024    db    0
    TopOfStack    equ    BaseOfLoader * 16 + $            ;


    Data32Len    equ $    - DATA32_START



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值