⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 st32_64.asm

📁 EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是EFI BIOS源代码中的与平台无关部分的代码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;------------------------------------------------------------------------------
;*
;*   Copyright 2006, Intel Corporation                                                         
;*   All rights reserved. This program and the accompanying materials                          
;*   are licensed and made available under the terms and conditions of the BSD License         
;*   which accompanies this distribution.  The full text of the license may be found at        
;*   http://opensource.org/licenses/bsd-license.php                                            
;*                                                                                             
;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
;*   
;*    st32_64.asm
;*  
;*   Abstract:
;*
;------------------------------------------------------------------------------

        .model  small
        .stack
        .486p
        .code

FAT_DIRECTORY_ENTRY_SIZE    EQU     020h
FAT_DIRECTORY_ENTRY_SHIFT   EQU     5
BLOCK_SIZE                  EQU     0200h
BLOCK_MASK                  EQU     01ffh
BLOCK_SHIFT                 EQU     9

;******************************************************************************
; Boot Sector and BPB (BIOS Parameter Block) structure
;******************************************************************************

        org 0h
Ia32Jump:
  jmp   BootSectorEntryPoint  ; JMP inst    - 3 bytes
  nop

OemId               db  "INTEL   "    ; OemId                           - 8 bytes
SectorSize          dw  0200h         ; Sector Size                     - 2 bytes
SectorsPerCluster   db  04h           ; Sector Per Cluster              - 1 byte
ReservedSectors     dw  0022h         ; Reserved Sectors                - 2 bytes
NoFats              db  02h           ; Number of FATs                  - 1 byte
RootEntries         dw  0000h         ; Root Entries                    - 2 bytes
Sectors             dw  0000h         ; Number of Sectors               - 2 bytes
Media               db  0f8h          ; Media                           - 1 byte
SectorsPerFat16     dw  0000h         ; Sectors Per FAT for FAT12/FAT16 - 2 byte
SectorsPerTrack     dw  003fh         ; Sectors Per Track               - 2 bytes
Heads               dw  00ffh         ; Heads                           - 2 bytes
HiddenSectors       dd  00000000h     ; Hidden Sectors                  - 4 bytes
LargeSectors        dd  0007bc00h     ; Large Sectors                   - 4 bytes

;******************************************************************************
;
;The structure for FAT32 starting at offset 36 of the boot sector. (At this point, 
;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
;
;******************************************************************************

SectorsPerFat32     dd  000003dbh     ; Sectors Per FAT for FAT32       - 4 bytes
ExtFlags            dw  0000h         ; Mirror Flag                     - 2 bytes
FSVersion           dw  0000h         ; File System Version             - 2 bytes
RootCluster         dd  00000002h     ; 1st Cluster Number of Root Dir  - 4 bytes
FSInfo              dw  0001h         ; Sector Number of FSINFO         - 2 bytes
BkBootSector        dw  0006h         ; Sector Number of Bk BootSector  - 2 bytes
Reserved            db  12 dup(0)     ; Reserved Field                  - 12 bytes
PhysicalDrive       db  00h           ; Physical Drive Number           - 1 byte
Reserved1           db  00h           ; Reserved Field                  - 1 byte
Signature           db  29h           ; Extended Boot Signature         - 1 byte
VolId               db  "    "        ; Volume Serial Number            - 4 bytes
FatLabel            db  "EFI FAT32  " ; Volume Label                    - 11 bytes
FileSystemType      db  "FAT32   "    ; File System Type                - 8 bytes

BootSectorEntryPoint:
        ASSUME  ds:@code
        ASSUME  ss:@code

; si      = NumberOfClusters
; cx      = ClusterNumber
; dx      = CachedFatSectorNumber
; ds:0000 = CacheFatSectorBuffer
; es:di   = Buffer to load file
; bx      = NextClusterNumber

        mov     si,0                                ; NumberOfClusters = 0 - Special case for first cluster
        xor     di,di                               ; di = 0
        mov     dx,0fffh                            ; CachedFatSectorNumber = 0xfff
        push    cx                                  ; Push StartCluster onto stack
FatChainLoop:
        mov     ax,cx                               ; ax = ClusterNumber    
        and     ax,0fff8h                           ; ax = ax & 0xfff8
        cmp     ax,0fff8h                           ; See if this is the last cluster
        je      FoundLastCluster                    ; Jump if last cluster found
        mov     ax,cx                               ; ax = ClusterNumber
        shl     ax,2                                ; FatOffset = ClusterNumber * 4
        push    si                                  ; Save si
        mov     si,ax                               ; si = FatOffset
        shr     ax,BLOCK_SHIFT                      ; ax = FatOffset >> BLOCK_SHIFT
        add     ax,word ptr [bp+ReservedSectors]    ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
        and     si,BLOCK_MASK                       ; si = FatOffset & BLOCK_MASK
        cmp     ax,dx                               ; Compare FatSectorNumber to CachedFatSectorNumber
        je      SkipFatRead
        mov     bx,2                                
        push    es
        push    ds
        pop     es
        call    ReadBlocks                          ; Read 2 blocks starting at AX storing at ES:DI
        pop     es
        mov     dx,ax                               ; CachedFatSectorNumber = FatSectorNumber
SkipFatRead:
        mov     bx,word ptr [si]                    ; bx = NextClusterNumber
        mov     ax,cx                               ; ax = ClusterNumber
        pop     si                                  ; Restore si

        cmp     si,0
        jne     NotFirstCluster
        mov     cx,bx
        pop     bx
        push    cx
        inc     si
        jmp     FatChainLoop
NotFirstCluster:

        dec     bx                                  ; bx = NextClusterNumber - 1
        cmp     bx,cx                               ; See if (NextClusterNumber-1)==ClusterNumber
        jne     ReadClusters
        inc     bx                                  ; bx = NextClusterNumber
        inc     si                                  ; NumberOfClusters++
        mov     cx,bx                               ; ClusterNumber = NextClusterNumber
        jmp     FatChainLoop
ReadClusters:
        inc     bx
        pop     ax                                  ; ax = StartCluster
        push    bx                                  ; StartCluster = NextClusterNumber
        mov     cx,bx                               ; ClusterNumber = NextClusterNumber
        sub     ax,2                                ; ax = StartCluster - 2
        xor     bh,bh                               
        mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster
        mul     bx                                  ; ax = (StartCluster - 2) * SectorsPerCluster
        add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
        push    ax                                  ; save start sector
        mov     ax,si                               ; ax = NumberOfClusters
        mul     bx                                  ; ax = NumberOfClusters * SectorsPerCluster
        mov     bx,ax                               ; bx = Number of Sectors
        pop     ax                                  ; ax = Start Sector
        call    ReadBlocks
        mov     si,1                                ; NumberOfClusters = 1
        jmp     FatChainLoop
FoundLastCluster:
        jmp     CheckEm64T
CheckEm64TPass:
        mov     ax,cs
        mov     word ptr cs:[JumpSegment],ax
JumpFarInstruction:
        db      0eah
JumpOffset:
        dw      0200h
JumpSegment:
        dw      2000h

; ****************************************************************************
; ReadBlocks - Reads a set of blocks from a block device
;
; AX    = Start LBA
; BX    = Number of Blocks to Read
; ES:DI = Buffer to store sectors read from disk
; ****************************************************************************

; cx = Blocks
; bx = NumberOfBlocks
; si = StartLBA

ReadBlocks:
        pusha
        add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA
        add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA
        mov     esi,eax                             ; esi = Start LBA
        mov     cx,bx                               ; cx = Number of blocks to read
ReadCylinderLoop:
        mov     bp,07bfch                           ; bp = 0x7bfc
        mov     eax,esi                             ; eax = Start LBA
        xor     dx,dx                               ; dx = 0
        movzx   ebx,word ptr [bp]                   ; bx = MaxSector
        div     ebx                                 ; ax = StartLBA / MaxSector
        inc     dx                                  ; dx = (StartLBA % MaxSector) + 1

        sub     bx,dx                               ; bx = MaxSector - Sector
        inc     bx                                  ; bx = MaxSector - Sector + 1
        cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)
        jg      LimitTransfer
        mov     bx,cx                               ; bx = Blocks
LimitTransfer:
        push    ax                                  ; save ax
        mov     ax,es                               ; ax = es
        shr     ax,(BLOCK_SHIFT-4)                  ; ax = Number of blocks into mem system
        and     ax,07fh                             ; ax = Number of blocks into current seg
        add     ax,bx                               ; ax = End Block number of transfer
        cmp     ax,080h                             ; See if it crosses a 64K boundry
        jle     NotCrossing64KBoundry               ; Branch if not crossing 64K boundry
        sub     ax,080h                             ; ax = Number of blocks past 64K boundry
        sub     bx,ax                               ; Decrease transfer size by block overage
NotCrossing64KBoundry:
        pop     ax                                  ; restore ax

        push    cx
        mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector
        xor     dx,dx                               ; dx = 0
        div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  
                                                    ; dx = ax % (MaxHead + 1) = Head

        push    bx                                  ; Save number of blocks to transfer
        mov     dh,dl                               ; dh = Head
        mov     bp,07c00h                           ; bp = 0x7c00
        mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number
        mov     ch,al                               ; ch = Cylinder
        mov     al,bl                               ; al = Blocks
        mov     ah,2                                ; ah = Function 2
        mov     bx,di                               ; es:bx = Buffer address
        int     013h
        jc      DiskError
        pop     bx
        pop     cx
        movzx   ebx,bx
        add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks
        sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks
        mov     ax,es
        shl     bx,(BLOCK_SHIFT-4)
        add     ax,bx
        mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
        cmp     cx,0
        jne     ReadCylinderLoop
        popa
        ret

DiskError:
        mov  ax,0b800h
        mov  es,ax
        mov  ax, 2000h
        mov  ds, ax
        lea  si, cs:[ErrorString]
        mov  cx, 11
        mov  di, 160
        rep  movsw 
Halt:
        jmp   Halt
ErrorString:
        db 'U', 0ch, 'O', 0ch, 'L', 0ch, ' ', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '2', 0ch, '!', 0ch
Em64String:
        db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
CheckEm64T:
        mov  eax, 080000001h
;        cpuid
        dw   0A20Fh
        bt   edx, 29
        jc   CheckEm64TPass

        mov  ax,0b800h
        mov  es,ax
        push cs
        pop  ds
        lea  si, cs:[Em64String]
        mov  cx, 18
        mov  di, 160
        rep  movsw 
        jmp  Halt

        org     01fah
LBAOffsetForBootSector:
        dd      0h

        org     01feh
        dw      0aa55h

;******************************************************************************
;******************************************************************************
;******************************************************************************

DELAY_PORT           equ     0edh    ; Port to use for 1uS delay
KBD_CONTROL_PORT     equ     060h    ; 8042 control port     
KBD_STATUS_PORT      equ     064h    ; 8042 status port      
WRITE_DATA_PORT_CMD  equ     0d1h    ; 8042 command to write the data port
ENABLE_A20_CMD       equ     0dfh    ; 8042 command to enable A20

        org     200h
start:  
        mov ax,cs
        mov ds,ax
        mov es,ax
        mov ss,ax
        mov sp,MyStack

        mov ax,0b800h
        mov es,ax
        mov byte ptr es:[160],'a'
        mov ax,cs
        mov es,ax

        mov ebx,0
        lea edi,MemoryMap
MemMapLoop:
        mov eax,0e820h
        mov ecx,20
        mov edx,'SMAP'
        int 15h
        jc  MemMapDone
        add edi,20
        cmp ebx,0
        je  MemMapDone
        jmp MemMapLoop
MemMapDone:
        lea eax,MemoryMap
        sub edi,eax                         ; Get the address of the memory map
        mov dword ptr [MemoryMapSize],edi   ; Save the size of the memory map

        xor     ebx,ebx
        mov     bx,cs                       ; BX=segment
        shl     ebx,4                       ; BX="linear" address of segment base
        lea     eax,[GDT_BASE + ebx]        ; EAX=PHYSICAL address of gdt
        mov     dword ptr [gdtr + 2],eax    ; Put address of gdt into the gdtr
        lea     eax,[IDT_BASE + ebx]        ; EAX=PHYSICAL address of idt
        mov     dword ptr [idtr + 2],eax    ; Put address of idt into the idtr
        lea     edx,[MemoryMapSize + ebx]   ; Physical base address of the memory map

;        add ebx,01000h                      ; Source of EFI32
;        mov dword ptr [JUMP+2],ebx
;        add ebx,01000h
;        mov esi,ebx                         ; Source of EFILDR32

        mov ax,0b800h
        mov es,ax
        mov byte ptr es:[162],'b'
        mov ax,cs
        mov es,ax

;
; Enable A20 Gate 
;

        mov ax,2401h                        ; Enable A20 Gate
        int 15h
        jnc A20GateEnabled                  ; Jump if it suceeded

;
; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
;

        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
        jnz     Timeout8042                 ; Jump if the 8042 timed out
        out     DELAY_PORT,ax               ; Delay 1 uS
        mov     al,WRITE_DATA_PORT_CMD      ; 8042 cmd to write output port
        out     KBD_STATUS_PORT,al          ; Send command to the 8042
        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
        jnz     Timeout8042                 ; Jump if the 8042 timed out
        mov     al,ENABLE_A20_CMD           ; gate address bit 20 on
        out     KBD_CONTROL_PORT,al         ; Send command to thre 8042
        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
        mov     cx,25                       ; Delay 25 uS for the command to complete on the 8042
Delay25uS:
        out     DELAY_PORT,ax               ; Delay 1 uS
        loop    Delay25uS                       
Timeout8042:


A20GateEnabled:

;
; DISABLE INTERRUPTS - Entering Protected Mode
;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -