📄 st32_64.asm
字号:
;------------------------------------------------------------------------------
;*
;* 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 + -