mirror of https://github.com/acidanthera/audk.git
Port Intel .asm to GNU .S
These .S files now is not for compiler but for us to control the version. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7549 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
32f9b796d3
commit
819958c65f
|
@ -0,0 +1,258 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#*
|
||||
#* Copyright 2006 - 2007, 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.
|
||||
#*
|
||||
#* Mbr.asm
|
||||
#*
|
||||
#* Abstract:
|
||||
#*
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
.equ BLOCK_SIZE, 0x0200
|
||||
.equ BLOCK_MASK, 0x01ff
|
||||
.equ BLOCK_SHIFT, 9
|
||||
|
||||
# ****************************************************************************
|
||||
# Code loaded by BIOS at 0x0000:0x7C00
|
||||
# ****************************************************************************
|
||||
|
||||
.org 0x0
|
||||
Start:
|
||||
|
||||
# ****************************************************************************
|
||||
# Start Print
|
||||
# ****************************************************************************
|
||||
|
||||
movw $0xb800, %ax
|
||||
movw %ax, %es
|
||||
movw $0x7c0, %ax
|
||||
movw %ax, %ds
|
||||
leaw %cs:StartString, %si
|
||||
movw $10, %cx
|
||||
movw $160, %di
|
||||
rep
|
||||
movsw
|
||||
|
||||
# ****************************************************************************
|
||||
# Print over
|
||||
# ****************************************************************************
|
||||
|
||||
# ****************************************************************************
|
||||
# Initialize segment registers and copy code at 0x0000:0x7c00 to 0x0000:0x0600
|
||||
# ****************************************************************************
|
||||
xorw %ax, %ax # AX = 0x0000
|
||||
movw $0x7c00, %bx # BX = 0x7C00
|
||||
movw $0x600, %bp # BP = 0x0600
|
||||
movw RelocatedStart, %si # SI = Offset(RelocatedStart)
|
||||
movw $0x200, %cx # CX = 0x0200
|
||||
subw %si, %cx # CS = 0x0200 - Offset(RelocatedStart)
|
||||
leaw (%bp,%si,), %di # DI = 0x0600 + Offset(RelocatedStart)
|
||||
leaw (%bx,%si,), %si # BX = 0x7C00 + Offset(RelocatedStart)
|
||||
movw %ax, %ss # SS = 0x0000
|
||||
movw %bx, %sp # SP = 0x7C00
|
||||
movw %ax, %es # ES = 0x0000
|
||||
movw %ax, %ds # DS = 0x0000
|
||||
pushw %ax # PUSH 0x0000
|
||||
pushw %di # PUSH 0x0600 + Offset(RelocatedStart)
|
||||
cld # Clear the direction flag
|
||||
rep
|
||||
movsb # Copy 0x0200 bytes from 0x7C00 to 0x0600
|
||||
retl # JMP 0x0000:0x0600 + Offset(RelocatedStart)
|
||||
|
||||
# ****************************************************************************
|
||||
# Code relocated to 0x0000:0x0600
|
||||
# ****************************************************************************
|
||||
|
||||
RelocatedStart:
|
||||
# ****************************************************************************
|
||||
# Get Driver Parameters to 0x0000:0x7BFC
|
||||
# ****************************************************************************
|
||||
|
||||
xorw %ax, %ax # AX = 0
|
||||
movw %ax, %ss # SS = 0
|
||||
addw $0x1000, %ax
|
||||
movw %ax, %ds
|
||||
|
||||
movw $0x7c00, %sp # SP = 0x7c00
|
||||
movw %sp, %bp # BP = 0x7c00
|
||||
|
||||
movb $8, %ah # AH = 8 - Get Drive Parameters Function
|
||||
movb %dl, PhysicalDrive(%bp) # BBS defines that BIOS would pass the booting driver number to the loader through DL
|
||||
int $0x13 # Get Drive Parameters
|
||||
xorw %ax, %ax # AX = 0
|
||||
movb %dh, %al # AL = DH
|
||||
incb %al # MaxHead = AL + 1
|
||||
pushw %ax # 0000:7bfe = MaxHead
|
||||
movb %cl, %al # AL = CL
|
||||
andb $0x3f, %al # MaxSector = AL & 0x3f
|
||||
pushw %ax # 0000:7bfc = MaxSector
|
||||
|
||||
# ****************************************************************************
|
||||
# Read Target DBR from hard disk to 0x0000:0x7C00
|
||||
# ****************************************************************************
|
||||
|
||||
xorw %ax, %ax
|
||||
movb MbrPartitionIndicator(%bp), %al # AX = MbrPartitionIndex
|
||||
cmpb $0xff, %al # 0xFF means do legacy MBR boot
|
||||
jnz EfiDbr
|
||||
LegacyMbr:
|
||||
movl $0x0000600, %eax # Assume LegacyMBR is backuped in Sector 6
|
||||
jmp StartReadTo7C00 # EAX = Header/Sector/Tracker/Zero
|
||||
|
||||
EfiDbr:
|
||||
cmpb $4, %al # MbrPartitionIndex should < 4
|
||||
jae BadDbr
|
||||
shlw $4, %ax # AX = MBREntrySize * Index
|
||||
addw $0x1be, %ax # AX = MBREntryOffset
|
||||
movw %ax, %di # DI = MBREntryOffset
|
||||
|
||||
# Here we don't use the C/H/S information provided by Partition table
|
||||
# but calculate C/H/S from LBA ourselves
|
||||
# Ci: Cylinder number
|
||||
# Hi: Header number
|
||||
# Si: Sector number
|
||||
movl %es:8(%bp,%di,), %eax # Start LBA
|
||||
movl %eax, %edx
|
||||
shrl $16, %edx # DX:AX = Start LBA
|
||||
# = Ci * (H * S) + Hi * S + (Si - 1)
|
||||
|
||||
# Calculate C/H/S according to LBA
|
||||
movw $0x7bfa, %bp
|
||||
divw 2(%bp) # AX = Hi + H*Ci
|
||||
# DX = Si - 1
|
||||
incw %dx # DX = Si
|
||||
pushw %dx # 0000:7bfa = Si <----
|
||||
xorw %dx, %dx # DX:AX = Hi + H*Ci
|
||||
divw 4(%bp) # AX = Ci <----
|
||||
# DX = Hi <----
|
||||
|
||||
StartReadTo7C00:
|
||||
|
||||
movb (%bp), %cl # Si
|
||||
movb %al, %ch # Ci[0-7]
|
||||
orb %ah, %cl # Ci[8,9]
|
||||
movw $0x7c00, %bx # ES:BX = 0000:7C00h
|
||||
movb $0x2, %ah # Function 02h
|
||||
movb $1, %al # 1 Sector
|
||||
movb %dl, %dh # Hi
|
||||
movw $0x600, %bp
|
||||
movb PhysicalDrive(%bp), %dl # Drive number
|
||||
int $0x13
|
||||
jc BadDbr
|
||||
|
||||
|
||||
|
||||
# ****************************************************************************
|
||||
# Transfer control to BootSector - Jump to 0x0000:0x7C00
|
||||
# ****************************************************************************
|
||||
xorw %ax, %ax
|
||||
pushw %ax # PUSH 0x0000 - Segment
|
||||
movw $0x7c00, %di
|
||||
pushw %di # PUSH 0x7C00 - Offset
|
||||
retl # JMP 0x0000:0x7C00
|
||||
|
||||
# ****************************************************************************
|
||||
# ERROR Condition:
|
||||
# ****************************************************************************
|
||||
|
||||
BadDbr:
|
||||
pushw %ax
|
||||
movw $0xb800, %ax
|
||||
movw %ax, %es
|
||||
movw $0x60, %ax
|
||||
movw %ax, %ds
|
||||
leaw %cs:ErrorString, %si
|
||||
movw $320, %di
|
||||
popw %ax
|
||||
call A2C
|
||||
movb %ah, 16(%si)
|
||||
movb %al, 18(%si)
|
||||
movw $10, %cx
|
||||
rep
|
||||
movsw
|
||||
Halt:
|
||||
jmp Halt
|
||||
|
||||
StartString:
|
||||
.byte 'M', 0x0c, 'B', 0x0c, 'R', 0x0c, ' ', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c
|
||||
ErrorString:
|
||||
.byte 'M', 0x0c, 'B', 0x0c, 'R', 0x0c, ' ', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, ':', 0x0c, '?', 0x0c, '?', 0x0c
|
||||
|
||||
# ****************************************************************************
|
||||
# A2C - convert Ascii code stored in AH to character stored in AX
|
||||
# ****************************************************************************
|
||||
A2C:
|
||||
movb %ah, %al
|
||||
shrb $4, %ah
|
||||
andb $0xF, %al
|
||||
addb '0', %ah
|
||||
addb '0', %al
|
||||
|
||||
cmpb '9', %ah
|
||||
jle A2C_L1
|
||||
addb $7, %ah
|
||||
A2C_L1:
|
||||
|
||||
cmpb '9', %al
|
||||
jle A2C_L2
|
||||
addb $7, %al
|
||||
A2C_L2:
|
||||
ret
|
||||
|
||||
|
||||
# ****************************************************************************
|
||||
# PhysicalDrive - Used to indicate which disk to be boot
|
||||
# Can be patched by tool
|
||||
# ****************************************************************************
|
||||
.org 0x01B6
|
||||
PhysicalDrive: .byte 0x80
|
||||
|
||||
# ****************************************************************************
|
||||
# MbrPartitionIndicator - Used to indicate which MBR partition to be boot
|
||||
# Can be patched by tool
|
||||
# OxFF means boot to legacy MBR. (LBA OFFSET 6)
|
||||
# ****************************************************************************
|
||||
.org 0x01B7
|
||||
MbrPartitionIndicator: .byte 0
|
||||
|
||||
# ****************************************************************************
|
||||
# Unique MBR signature
|
||||
# ****************************************************************************
|
||||
.org 0x01B8
|
||||
.ascii "DUET"
|
||||
|
||||
# ****************************************************************************
|
||||
# Unknown
|
||||
# ****************************************************************************
|
||||
.org 0x01BC
|
||||
.word 0
|
||||
|
||||
# ****************************************************************************
|
||||
# MBR Entry - To be patched
|
||||
# ****************************************************************************
|
||||
.org 0x01BE
|
||||
.long 0,0,0,0
|
||||
.org 0x01CE
|
||||
.long 0,0,0,0
|
||||
.org 0x01DE
|
||||
.long 0,0,0,0
|
||||
.org 0x01EE
|
||||
.long 0,0,0,0
|
||||
|
||||
# ****************************************************************************
|
||||
# Sector Signature
|
||||
# ****************************************************************************
|
||||
|
||||
.org 0x01FE
|
||||
SectorSignature:
|
||||
.word 0xaa55 # Boot Sector Signature
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#*
|
||||
#* Copyright 2006 - 2007, 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.
|
||||
#*
|
||||
#* bootsect.asm
|
||||
#*
|
||||
#* Abstract:
|
||||
#*
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#.MODEL small
|
||||
.stack:
|
||||
.486p:
|
||||
.code:
|
||||
|
||||
.equ FAT_DIRECTORY_ENTRY_SIZE, 0x020
|
||||
.equ FAT_DIRECTORY_ENTRY_SHIFT, 5
|
||||
.equ BLOCK_SIZE, 0x0200
|
||||
.equ BLOCK_MASK, 0x01ff
|
||||
.equ BLOCK_SHIFT, 9
|
||||
# "EFILDR_____"
|
||||
.equ LOADER_FILENAME_PART1, 0x04c494645 # "EFIL"
|
||||
.equ LOADER_FILENAME_PART2, 0x020205244 # "DR__"
|
||||
.equ LOADER_FILENAME_PART3, 0x020202020 # "____"
|
||||
|
||||
.org 0x0
|
||||
Ia32Jump:
|
||||
jmp BootSectorEntryPoint # JMP inst - 3 bytes
|
||||
nop
|
||||
|
||||
OemId: .ascii "INTEL " # OemId - 8 bytes
|
||||
# BPB data below will be fixed by tool
|
||||
SectorSize: .word 0 # Sector Size - 16 bits
|
||||
SectorsPerCluster: .byte 0 # Sector Per Cluster - 8 bits
|
||||
ReservedSectors: .word 0 # Reserved Sectors - 16 bits
|
||||
NoFats: .byte 0 # Number of FATs - 8 bits
|
||||
RootEntries: .word 0 # Root Entries - 16 bits
|
||||
Sectors: .word 0 # Number of Sectors - 16 bits
|
||||
Media: .byte 0 # Media - 8 bits - ignored
|
||||
SectorsPerFat: .word 0 # Sectors Per FAT - 16 bits
|
||||
SectorsPerTrack: .word 0 # Sectors Per Track - 16 bits - ignored
|
||||
Heads: .word 0 # Heads - 16 bits - ignored
|
||||
HiddenSectors: .long 0 # Hidden Sectors - 32 bits - ignored
|
||||
LargeSectors: .long 0 # Large Sectors - 32 bits
|
||||
PhysicalDrive: .byte 0 # PhysicalDriveNumber - 8 bits - ignored
|
||||
CurrentHead: .byte 0 # Current Head - 8 bits
|
||||
Signature: .byte 0 # Signature - 8 bits - ignored
|
||||
VolId: .ascii " " # Volume Serial Number- 4 bytes
|
||||
FatLabel: .ascii " " # Label - 11 bytes
|
||||
SystemId: .ascii "FAT12 " # SystemId - 8 bytes
|
||||
|
||||
BootSectorEntryPoint:
|
||||
#ASSUME ds:@code
|
||||
#ASSUME ss:@code
|
||||
|
||||
# ****************************************************************************
|
||||
# Start Print
|
||||
# ****************************************************************************
|
||||
leaw %cs:StartString, %si
|
||||
call PrintString
|
||||
|
||||
# ****************************************************************************
|
||||
# Print over
|
||||
# ****************************************************************************
|
||||
|
||||
movw %cs, %ax # ax = 0
|
||||
movw %ax, %ss # ss = 0
|
||||
addw $0x1000, %ax
|
||||
movw %ax, %ds
|
||||
|
||||
movw $0x7c00, %sp # sp = 0x7c00
|
||||
movw %sp, %bp # bp = 0x7c00
|
||||
|
||||
movb $8, %ah # ah = 8 - Get Drive Parameters Function
|
||||
movb %dl, PhysicalDrive(%bp) # BBS defines that BIOS would pass the booting driver number to the loader through DL
|
||||
int $0x13 # Get Drive Parameters
|
||||
xorw %ax, %ax # ax = 0
|
||||
movb %dh, %al # al = dh
|
||||
incb %al # MaxHead = al + 1
|
||||
pushw %ax # 0000:7bfe = MaxHead
|
||||
movb %cl, %al # al = cl
|
||||
andb $0x3f, %al # MaxSector = al & 0x3f
|
||||
pushw %ax # 0000:7bfc = MaxSector
|
||||
|
||||
cmpw $0xaa55, SectorSignature(%bp) # Verify Boot Sector Signature
|
||||
jne BadBootSector
|
||||
movw RootEntries(%bp), %cx # cx = RootEntries
|
||||
shlw $FAT_DIRECTORY_ENTRY_SHIFT, %cx # cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
|
||||
movw %cx, %bx # bx = size of the Root Directory in bytes
|
||||
andw $BLOCK_MASK, %bx # See if it is an even number of sectors long
|
||||
jne BadBootSector # If is isn't, then the boot sector is bad.
|
||||
movw %cx, %bx # bx = size of the Root Directory in bytes
|
||||
shrw $BLOCK_SHIFT, %bx # bx = size of Root Directory in sectors
|
||||
movb NoFats(%bp), %al # al = NoFats
|
||||
xorb %ah, %ah # ah = 0 ==> ax = NoFats
|
||||
mulw SectorsPerFat(%bp) # ax = NoFats * SectorsPerFat
|
||||
addw ReservedSectors(%bp), %ax # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
|
||||
pushw %ds
|
||||
popw %es
|
||||
xorw %di, %di # Store directory in es:di = 1000:0000
|
||||
call ReadBlocks # Read entire Root Directory
|
||||
addw %bx, %ax # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
|
||||
movw %ax, (%bp) # Save FirstClusterLBA (FirstDataSector) for later use
|
||||
|
||||
# dx - variable storage (initial value is 0)
|
||||
# bx - loader (initial value is 0)
|
||||
xorw %dx, %dx
|
||||
xorw %bx, %bx
|
||||
|
||||
FindEFILDR:
|
||||
cmpl $LOADER_FILENAME_PART1, (%di) # Compare to "EFIL"
|
||||
jne FindVARSTORE
|
||||
cmpl $LOADER_FILENAME_PART2, 4(%di)
|
||||
jne FindVARSTORE
|
||||
cmpl $LOADER_FILENAME_PART3, 7(%di)
|
||||
jne FindVARSTORE
|
||||
movw 26(%di), %bx # bx = Start Cluster for EFILDR <----------------------------------
|
||||
testw %dx, %dx
|
||||
je FindNext # Efivar.bin is not loaded
|
||||
jmp FoundAll
|
||||
|
||||
FindVARSTORE:
|
||||
## if the file is not loader file, see if it's "EFIVAR BIN"
|
||||
cmpl $0x56494645, (%di) # Compare to "EFIV"
|
||||
jne FindNext
|
||||
cmpl $0x20205241, 4(%di) # Compare to "AR "
|
||||
jne FindNext
|
||||
cmpl $0x4e494220, 7(%di) # Compare to " BIN"
|
||||
jne FindNext
|
||||
movw %di, %dx # dx = Offset of Start Cluster for Efivar.bin <---------------------
|
||||
addw $26, %dx
|
||||
testw %bx, %bx
|
||||
je FindNext # Efildr is not loaded
|
||||
jmp FoundAll
|
||||
|
||||
FindNext:
|
||||
# go to next find
|
||||
addw $FAT_DIRECTORY_ENTRY_SIZE, %di # Increment di
|
||||
subw $FAT_DIRECTORY_ENTRY_SIZE, %cx # Decrement cx
|
||||
# TODO: jump to FindVarStore if ...
|
||||
jne FindEFILDR
|
||||
jmp NotFoundAll
|
||||
|
||||
FoundAll:
|
||||
FoundEFILDR:
|
||||
movw %bx, %cx # cx = Start Cluster for EFILDR <----------------------------------
|
||||
movw %cs, %ax # Destination = 2000:0000
|
||||
addw $0x2000, %ax
|
||||
movw %ax, %es
|
||||
xorw %di, %di
|
||||
ReadFirstClusterOfEFILDR:
|
||||
movw %cx, %ax # ax = StartCluster
|
||||
subw $2, %ax # ax = StartCluster - 2
|
||||
xorb %bh, %bh
|
||||
movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
|
||||
pushw %dx
|
||||
mulw %bx
|
||||
popw %dx # ax = (StartCluster - 2) * SectorsPerCluster
|
||||
addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
|
||||
xorb %bh, %bh
|
||||
movb SectorsPerCluster(%bp), %bl # bx = Number of Sectors in a cluster
|
||||
pushw %es
|
||||
call ReadBlocks
|
||||
popw %ax
|
||||
JumpIntoFirstSectorOfEFILDR:
|
||||
movw %ax, JumpSegment(%bp)
|
||||
JumpFarInstruction:
|
||||
.byte 0xea
|
||||
JumpOffset:
|
||||
.word 0x000
|
||||
JumpSegment:
|
||||
.word 0x2000
|
||||
|
||||
|
||||
PrintString:
|
||||
movw $0xb800, %ax
|
||||
movw %ax, %es
|
||||
movw $0x7c0, %ax
|
||||
movw %ax, %ds
|
||||
movw $7, %cx
|
||||
movw $160, %di
|
||||
rep
|
||||
movsw
|
||||
ret
|
||||
# ****************************************************************************
|
||||
# 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
|
||||
addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA
|
||||
addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA
|
||||
movl %eax, %esi # esi = Start LBA
|
||||
movw %bx, %cx # cx = Number of blocks to read
|
||||
ReadCylinderLoop:
|
||||
movw $0x7bfc, %bp # bp = 0x7bfc
|
||||
movl %esi, %eax # eax = Start LBA
|
||||
xorl %edx, %edx # edx = 0
|
||||
movzwl (%bp), %ebx # bx = MaxSector
|
||||
divl %ebx # ax = StartLBA / MaxSector
|
||||
incw %dx # dx = (StartLBA % MaxSector) + 1
|
||||
subw %dx, %bx # bx = MaxSector - Sector
|
||||
incw %bx # bx = MaxSector - Sector + 1
|
||||
cmpw %bx, %cx # Compare (Blocks) to (MaxSector - Sector + 1)
|
||||
jg LimitTransfer
|
||||
movw %cx, %bx # bx = Blocks
|
||||
LimitTransfer:
|
||||
pushw %cx
|
||||
movb %dl, %cl # cl = (StartLBA % MaxSector) + 1 = Sector
|
||||
xorw %dx, %dx # dx = 0
|
||||
divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder
|
||||
# dx = ax % (MaxHead + 1) = Head
|
||||
|
||||
pushw %bx # Save number of blocks to transfer
|
||||
movb %dl, %dh # dh = Head
|
||||
movw $0x7c00, %bp # bp = 0x7c00
|
||||
movb PhysicalDrive(%bp), %dl # dl = Drive Number
|
||||
movb %al, %ch # ch = Cylinder
|
||||
movb %bl, %al # al = Blocks
|
||||
movb $2, %ah # ah = Function 2
|
||||
movw %di, %bx # es:bx = Buffer address
|
||||
int $0x13
|
||||
jc DiskError
|
||||
popw %bx
|
||||
popw %cx
|
||||
movzwl %bx, %ebx
|
||||
addl %ebx, %esi # StartLBA = StartLBA + NumberOfBlocks
|
||||
subw %bx, %cx # Blocks = Blocks - NumberOfBlocks
|
||||
movw %es, %ax
|
||||
shlw $(BLOCK_SHIFT-4), %bx
|
||||
addw %bx, %ax
|
||||
movw %ax, %es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE
|
||||
cmpw $0, %cx
|
||||
jne ReadCylinderLoop
|
||||
popa
|
||||
ret
|
||||
|
||||
# ****************************************************************************
|
||||
# ERROR Condition:
|
||||
# ****************************************************************************
|
||||
NotFoundAll:
|
||||
## if we found EFILDR, continue
|
||||
testw %bx, %bx
|
||||
jne FoundEFILDR
|
||||
BadBootSector:
|
||||
DiskError:
|
||||
leaw %cs:ErrorString, %si
|
||||
call PrintString
|
||||
Halt:
|
||||
jmp Halt
|
||||
|
||||
StartString:
|
||||
.byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c
|
||||
ErrorString:
|
||||
.byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c
|
||||
|
||||
# ****************************************************************************
|
||||
# LBA Offset for BootSector, need patched by tool for HD boot.
|
||||
# ****************************************************************************
|
||||
|
||||
# .org 0x01fa # Comment it for pass build. Should optimise code size.
|
||||
LBAOffsetForBootSector:
|
||||
.long 0x0
|
||||
|
||||
# ****************************************************************************
|
||||
# Sector Signature
|
||||
# ****************************************************************************
|
||||
|
||||
# .org 0x01fe # Comment it for pass build.
|
||||
SectorSignature:
|
||||
.word 0xaa55 # Boot Sector Signature
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#*
|
||||
#* Copyright 2006 - 2007, 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.
|
||||
#*
|
||||
#* bs16.asm
|
||||
#*
|
||||
#* Abstract:
|
||||
#*
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#.MODEL small
|
||||
.stack:
|
||||
.486p:
|
||||
.code:
|
||||
|
||||
.equ FAT_DIRECTORY_ENTRY_SIZE, 0x020
|
||||
.equ FAT_DIRECTORY_ENTRY_SHIFT, 5
|
||||
.equ BLOCK_SIZE, 0x0200
|
||||
.equ BLOCK_MASK, 0x01ff
|
||||
.equ BLOCK_SHIFT, 9
|
||||
# "EFILDR_____"
|
||||
.equ LOADER_FILENAME_PART1, 0x04c494645 # "EFIL"
|
||||
.equ LOADER_FILENAME_PART2, 0x036315244 # "DR16"
|
||||
.equ LOADER_FILENAME_PART3, 0x020202036 # "6___"
|
||||
|
||||
.org 0x0
|
||||
Ia32Jump:
|
||||
jmp BootSectorEntryPoint # JMP inst - 3 bytes
|
||||
nop
|
||||
|
||||
OemId: .ascii "INTEL " # OemId - 8 bytes
|
||||
# BPB data below will be fixed by tool
|
||||
SectorSize: .word 0 # Sector Size - 16 bits
|
||||
SectorsPerCluster: .byte 0 # Sector Per Cluster - 8 bits
|
||||
ReservedSectors: .word 0 # Reserved Sectors - 16 bits
|
||||
NoFats: .byte 0 # Number of FATs - 8 bits
|
||||
RootEntries: .word 0 # Root Entries - 16 bits
|
||||
Sectors: .word 0 # Number of Sectors - 16 bits
|
||||
Media: .byte 0 # Media - 8 bits - ignored
|
||||
SectorsPerFat: .word 0 # Sectors Per FAT - 16 bits
|
||||
SectorsPerTrack: .word 0 # Sectors Per Track - 16 bits - ignored
|
||||
Heads: .word 0 # Heads - 16 bits - ignored
|
||||
HiddenSectors: .long 0 # Hidden Sectors - 32 bits - ignored
|
||||
LargeSectors: .long 0 # Large Sectors - 32 bits
|
||||
PhysicalDrive: .byte 0 # PhysicalDriveNumber - 8 bits - ignored
|
||||
CurrentHead: .byte 0 # Current Head - 8 bits
|
||||
Signature: .byte 0 # Signature - 8 bits - ignored
|
||||
VolId: .ascii " " # Volume Serial Number- 4 bytes
|
||||
FatLabel: .ascii " " # Label - 11 bytes
|
||||
SystemId: .ascii "FAT12 " # SystemId - 8 bytes
|
||||
|
||||
BootSectorEntryPoint:
|
||||
#ASSUME ds:@code
|
||||
#ASSUME ss:@code
|
||||
|
||||
# ****************************************************************************
|
||||
# Start Print
|
||||
# ****************************************************************************
|
||||
leaw %cs:StartString, %si
|
||||
call PrintString
|
||||
|
||||
# ****************************************************************************
|
||||
# Print over
|
||||
# ****************************************************************************
|
||||
|
||||
movw %cs, %ax # ax = 0
|
||||
movw %ax, %ss # ss = 0
|
||||
addw $0x1000, %ax
|
||||
movw %ax, %ds
|
||||
|
||||
movw $0x7c00, %sp # sp = 0x7c00
|
||||
movw %sp, %bp # bp = 0x7c00
|
||||
|
||||
movb $8, %ah # ah = 8 - Get Drive Parameters Function
|
||||
movb %dl, PhysicalDrive(%bp) # BBS defines that BIOS would pass the booting driver number to the loader through DL
|
||||
int $0x13 # Get Drive Parameters
|
||||
xorw %ax, %ax # ax = 0
|
||||
movb %dh, %al # al = dh
|
||||
incb %al # MaxHead = al + 1
|
||||
pushw %ax # 0000:7bfe = MaxHead
|
||||
movb %cl, %al # al = cl
|
||||
andb $0x3f, %al # MaxSector = al & 0x3f
|
||||
pushw %ax # 0000:7bfc = MaxSector
|
||||
|
||||
cmpw $0xaa55, SectorSignature(%bp) # Verify Boot Sector Signature
|
||||
jne BadBootSector
|
||||
movw RootEntries(%bp), %cx # cx = RootEntries
|
||||
shlw $FAT_DIRECTORY_ENTRY_SHIFT, %cx # cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
|
||||
movw %cx, %bx # bx = size of the Root Directory in bytes
|
||||
andw $BLOCK_MASK, %bx # See if it is an even number of sectors long
|
||||
jne BadBootSector # If is isn't, then the boot sector is bad.
|
||||
movw %cx, %bx # bx = size of the Root Directory in bytes
|
||||
shrw $BLOCK_SHIFT, %bx # bx = size of Root Directory in sectors
|
||||
movb NoFats(%bp), %al # al = NoFats
|
||||
xorb %ah, %ah # ah = 0 ==> ax = NoFats
|
||||
mulw SectorsPerFat(%bp) # ax = NoFats * SectorsPerFat
|
||||
addw ReservedSectors(%bp), %ax # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
|
||||
pushw %ds
|
||||
popw %es
|
||||
xorw %di, %di # Store directory in es:di = 1000:0000
|
||||
call ReadBlocks # Read entire Root Directory
|
||||
addw %bx, %ax # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
|
||||
movw %ax, (%bp) # Save FirstClusterLBA (FirstDataSector) for later use
|
||||
|
||||
# dx - variable storage (initial value is 0)
|
||||
# bx - loader (initial value is 0)
|
||||
xorw %dx, %dx
|
||||
xorw %bx, %bx
|
||||
|
||||
FindEFILDR:
|
||||
cmpl $LOADER_FILENAME_PART1, (%di) # Compare to "EFIL"
|
||||
jne FindVARSTORE
|
||||
cmpl $LOADER_FILENAME_PART2, 4(%di)
|
||||
jne FindVARSTORE
|
||||
cmpl $LOADER_FILENAME_PART3, 7(%di)
|
||||
jne FindVARSTORE
|
||||
movw 26(%di), %bx # bx = Start Cluster for EFILDR <----------------------------------
|
||||
testw %dx, %dx
|
||||
je FindNext # Efivar.bin is not loaded
|
||||
jmp FoundAll
|
||||
|
||||
FindVARSTORE:
|
||||
##if the file is not loader file, see if it's "EFIVAR BIN"
|
||||
cmpl $0x56494645, (%di) # Compare to "EFIV"
|
||||
jne FindNext
|
||||
cmpl $0x20205241, 4(%di) # Compare to "AR "
|
||||
jne FindNext
|
||||
cmpl $0x4e494220, 7(%di) # Compare to " BIN"
|
||||
jne FindNext
|
||||
movw %di, %dx # dx = Offset of Start Cluster for Efivar.bin <---------------------
|
||||
addw $26, %dx
|
||||
testw %bx, %bx
|
||||
je FindNext # Efildr is not loaded
|
||||
jmp FoundAll
|
||||
|
||||
FindNext:
|
||||
# go to next find
|
||||
addw $FAT_DIRECTORY_ENTRY_SIZE, %di # Increment di
|
||||
subw $FAT_DIRECTORY_ENTRY_SIZE, %cx # Decrement cx
|
||||
# TODO: jump to FindVarStore if ...
|
||||
jne FindEFILDR
|
||||
jmp NotFoundAll
|
||||
|
||||
FoundAll:
|
||||
FoundEFILDR:
|
||||
movw %bx, %cx # cx = Start Cluster for EFILDR <----------------------------------
|
||||
movw %cs, %ax # Destination = 2000:0000
|
||||
addw $0x2000, %ax
|
||||
movw %ax, %es
|
||||
xorw %di, %di
|
||||
ReadFirstClusterOfEFILDR:
|
||||
movw %cx, %ax # ax = StartCluster
|
||||
subw $2, %ax # ax = StartCluster - 2
|
||||
xorb %bh, %bh
|
||||
movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
|
||||
pushw %dx
|
||||
mulw %bx
|
||||
popw %dx # ax = (StartCluster - 2) * SectorsPerCluster
|
||||
addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
|
||||
xorb %bh, %bh
|
||||
movb SectorsPerCluster(%bp), %bl # bx = Number of Sectors in a cluster
|
||||
pushw %es
|
||||
call ReadBlocks
|
||||
popw %ax
|
||||
JumpIntoFirstSectorOfEFILDR:
|
||||
movw %ax, JumpSegment(%bp)
|
||||
JumpFarInstruction:
|
||||
.byte 0xea
|
||||
JumpOffset:
|
||||
.word 0x000
|
||||
JumpSegment:
|
||||
.word 0x2000
|
||||
|
||||
|
||||
PrintString:
|
||||
movw $0xb800, %ax
|
||||
movw %ax, %es
|
||||
movw $0x7c0, %ax
|
||||
movw %ax, %ds
|
||||
movw $7, %cx
|
||||
movw $160, %di
|
||||
rep
|
||||
movsw
|
||||
ret
|
||||
# ****************************************************************************
|
||||
# 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
|
||||
addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA
|
||||
addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA
|
||||
movl %eax, %esi # esi = Start LBA
|
||||
movw %bx, %cx # cx = Number of blocks to read
|
||||
ReadCylinderLoop:
|
||||
movw $0x7bfc, %bp # bp = 0x7bfc
|
||||
movl %esi, %eax # eax = Start LBA
|
||||
xorl %edx, %edx # edx = 0
|
||||
movzwl (%bp), %ebx # bx = MaxSector
|
||||
divl %ebx # ax = StartLBA / MaxSector
|
||||
incw %dx # dx = (StartLBA % MaxSector) + 1
|
||||
subw %dx, %bx # bx = MaxSector - Sector
|
||||
incw %bx # bx = MaxSector - Sector + 1
|
||||
cmpw %bx, %cx # Compare (Blocks) to (MaxSector - Sector + 1)
|
||||
jg LimitTransfer
|
||||
movw %cx, %bx # bx = Blocks
|
||||
LimitTransfer:
|
||||
pushw %cx
|
||||
movb %dl, %cl # cl = (StartLBA % MaxSector) + 1 = Sector
|
||||
xorw %dx, %dx # dx = 0
|
||||
divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder
|
||||
# dx = ax % (MaxHead + 1) = Head
|
||||
|
||||
pushw %bx # Save number of blocks to transfer
|
||||
movb %dl, %dh # dh = Head
|
||||
movw $0x7c00, %bp # bp = 0x7c00
|
||||
movb PhysicalDrive(%bp), %dl # dl = Drive Number
|
||||
movb %al, %ch # ch = Cylinder
|
||||
movb %bl, %al # al = Blocks
|
||||
movb $2, %ah # ah = Function 2
|
||||
movw %di, %bx # es:bx = Buffer address
|
||||
int $0x13
|
||||
jc DiskError
|
||||
popw %bx
|
||||
popw %cx
|
||||
movzwl %bx, %ebx
|
||||
addl %ebx, %esi # StartLBA = StartLBA + NumberOfBlocks
|
||||
subw %bx, %cx # Blocks = Blocks - NumberOfBlocks
|
||||
movw %es, %ax
|
||||
shlw $(BLOCK_SHIFT-4),%bx
|
||||
addw %bx, %ax
|
||||
movw %ax, %es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE
|
||||
cmpw $0, %cx
|
||||
jne ReadCylinderLoop
|
||||
popa
|
||||
ret
|
||||
|
||||
# ****************************************************************************
|
||||
# ERROR Condition:
|
||||
# ****************************************************************************
|
||||
NotFoundAll:
|
||||
## if we found EFILDR, continue
|
||||
testw %bx, %bx
|
||||
jne FoundEFILDR
|
||||
BadBootSector:
|
||||
DiskError:
|
||||
leaw %cs:ErrorString, %si
|
||||
call PrintString
|
||||
Halt:
|
||||
jmp Halt
|
||||
|
||||
StartString:
|
||||
.byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c
|
||||
ErrorString:
|
||||
.byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c
|
||||
|
||||
# ****************************************************************************
|
||||
# LBA Offset for BootSector, need patched by tool for HD boot.
|
||||
# ****************************************************************************
|
||||
|
||||
# .org 0x01fa # Comment it for pass build. Should optimise code size.
|
||||
LBAOffsetForBootSector:
|
||||
.long 0x0
|
||||
|
||||
# ****************************************************************************
|
||||
# Sector Signature
|
||||
# ****************************************************************************
|
||||
|
||||
# .org 0x01fe # Comment it for pass build. Should optimise code size.
|
||||
SectorSignature:
|
||||
.word 0xaa55 # Boot Sector Signature
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,916 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#*
|
||||
#* Copyright 2006 - 2007, 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.
|
||||
#*
|
||||
#* start.S
|
||||
#*
|
||||
#* Abstract:
|
||||
#*
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
.equ FAT_DIRECTORY_ENTRY_SIZE, 0x020
|
||||
.equ FAT_DIRECTORY_ENTRY_SHIFT, 5
|
||||
.equ BLOCK_SIZE, 0x0200
|
||||
.equ BLOCK_MASK, 0x01ff
|
||||
.equ BLOCK_SHIFT, 9
|
||||
|
||||
.org 0x0
|
||||
Ia32Jump:
|
||||
jmp BootSectorEntryPoint # JMP inst - 3 bytes
|
||||
nop
|
||||
|
||||
OemId: .ascii "INTEL " # OemId - 8 bytes
|
||||
|
||||
SectorSize: .word 0 # Sector Size - 16 bits
|
||||
SectorsPerCluster: .byte 0 # Sector Per Cluster - 8 bits
|
||||
ReservedSectors: .word 0 # Reserved Sectors - 16 bits
|
||||
NoFats: .byte 0 # Number of FATs - 8 bits
|
||||
RootEntries: .word 0 # Root Entries - 16 bits
|
||||
Sectors: .word 0 # Number of Sectors - 16 bits
|
||||
Media: .byte 0 # Media - 8 bits - ignored
|
||||
SectorsPerFat: .word 0 # Sectors Per FAT - 16 bits
|
||||
SectorsPerTrack: .word 0 # Sectors Per Track - 16 bits - ignored
|
||||
Heads: .word 0 # Heads - 16 bits - ignored
|
||||
HiddenSectors: .long 0 # Hidden Sectors - 32 bits - ignored
|
||||
LargeSectors: .long 0 # Large Sectors - 32 bits
|
||||
PhysicalDrive: .byte 0 # PhysicalDriveNumber - 8 bits - ignored
|
||||
CurrentHead: .byte 0 # Current Head - 8 bits
|
||||
Signature: .byte 0 # Signature - 8 bits - ignored
|
||||
VolId: .ascii " " # Volume Serial Number- 4 bytes
|
||||
FatLabel: .ascii " " # Label - 11 bytes
|
||||
SystemId: .ascii "FAT12 " # SystemId - 8 bytes
|
||||
|
||||
BootSectorEntryPoint:
|
||||
#ASSUME ds:@code
|
||||
#ASSUME ss:@code
|
||||
# ds = 1000, es = 2000 + x (size of first cluster >> 4)
|
||||
# cx = Start Cluster of EfiLdr
|
||||
# dx = Start Cluster of Efivar.bin
|
||||
|
||||
# Re use the BPB data stored in Boot Sector
|
||||
movw $0x7c00, %bp
|
||||
|
||||
pushw %cx
|
||||
# Read Efivar.bin
|
||||
# 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
|
||||
movw $0x1900, %ax
|
||||
movw %ax, %es
|
||||
testw %dx, %dx
|
||||
jnz CheckVarStoreSize
|
||||
|
||||
movb $1, %al
|
||||
NoVarStore:
|
||||
pushw %es
|
||||
# Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
|
||||
movb %al, %es:($4)
|
||||
jmp SaveVolumeId
|
||||
|
||||
CheckVarStoreSize:
|
||||
movw %dx, %di
|
||||
cmpl $0x4000, %ds:2(%di)
|
||||
movb $2, %al
|
||||
jne NoVarStore
|
||||
|
||||
LoadVarStore:
|
||||
movb $0, %al
|
||||
movb %al, %es:($4)
|
||||
movw (%di), %cx
|
||||
# ES:DI = 1500:0
|
||||
xorw %di, %di
|
||||
pushw %es
|
||||
movw $0x1500, %ax
|
||||
movw %ax, %es
|
||||
call ReadFile
|
||||
SaveVolumeId:
|
||||
popw %es
|
||||
movw VolId(%bp), %ax
|
||||
movw %ax, %es:($0) # Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
|
||||
movw VolId+2(%bp), %ax
|
||||
movw %ax, %es:($2)
|
||||
|
||||
# Read Efildr
|
||||
popw %cx
|
||||
# cx = Start Cluster of Efildr -> BS.com has filled already
|
||||
# ES:DI = 2000:0, first cluster will be read again
|
||||
xorw %di, %di # di = 0
|
||||
movw $0x2000, %ax
|
||||
movw %ax, %es
|
||||
call ReadFile
|
||||
movw %cs, %ax
|
||||
movw %ax, %cs:JumpSegment
|
||||
|
||||
JumpFarInstruction:
|
||||
.byte 0xea
|
||||
JumpOffset:
|
||||
.word 0x200
|
||||
JumpSegment:
|
||||
.word 0x2000
|
||||
|
||||
|
||||
|
||||
# ****************************************************************************
|
||||
# ReadFile
|
||||
#
|
||||
# Arguments:
|
||||
# CX = Start Cluster of File
|
||||
# ES:DI = Buffer to store file content read from disk
|
||||
#
|
||||
# Return:
|
||||
# (ES << 4 + DI) = end of file content Buffer
|
||||
#
|
||||
# ****************************************************************************
|
||||
ReadFile:
|
||||
# si = NumberOfClusters
|
||||
# cx = ClusterNumber
|
||||
# dx = CachedFatSectorNumber
|
||||
# ds:0000 = CacheFatSectorBuffer
|
||||
# es:di = Buffer to load file
|
||||
# bx = NextClusterNumber
|
||||
pusha
|
||||
movw $1, %si # NumberOfClusters = 1
|
||||
pushw %cx # Push Start Cluster onto stack
|
||||
movw $0xfff, %dx # CachedFatSectorNumber = 0xfff
|
||||
FatChainLoop:
|
||||
movw %cx, %ax # ax = ClusterNumber
|
||||
andw $0xff8, %ax # ax = ax & 0xff8
|
||||
cmpw $0xff8, %ax # See if this is the last cluster
|
||||
je FoundLastCluster # Jump if last cluster found
|
||||
movw %cx, %ax # ax = ClusterNumber
|
||||
shlw %ax # ax = ClusterNumber * 2
|
||||
addw %cx, %ax # ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3
|
||||
shrw %ax # FatOffset = ClusterNumber*3 / 2
|
||||
pushw %si # Save si
|
||||
movw %ax, %si # si = FatOffset
|
||||
shrw %ax # ax = FatOffset >> BLOCK_SHIFT
|
||||
addw ReservedSectors(%bp), %ax # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
|
||||
andw BLOCK_MASK,%si # si = FatOffset & BLOCK_MASK
|
||||
cmpw %dx, %ax # Compare FatSectorNumber to CachedFatSectorNumber
|
||||
je SkipFatRead
|
||||
movw $2, %bx
|
||||
pushw %es
|
||||
pushw %ds
|
||||
popw %es
|
||||
call ReadBlocks # Read 2 blocks starting at AX storing at ES:DI
|
||||
popw %es
|
||||
movw %ax, %dx # CachedFatSectorNumber = FatSectorNumber
|
||||
SkipFatRead:
|
||||
movw (%si), %bx # bx = NextClusterNumber
|
||||
movw %cx, %ax # ax = ClusterNumber
|
||||
andw $1, %ax # See if this is an odd cluster number
|
||||
je EvenFatEntry
|
||||
shrw $4, %bx # NextClusterNumber = NextClusterNumber >> 4
|
||||
EvenFatEntry:
|
||||
andw $0xfff, %bx # Strip upper 4 bits of NextClusterNumber
|
||||
popw %si # Restore si
|
||||
decw %bx # bx = NextClusterNumber - 1
|
||||
cmpw %cx, %bx # See if (NextClusterNumber-1)==ClusterNumber
|
||||
jne ReadClusters
|
||||
incw %bx # bx = NextClusterNumber
|
||||
incw %si # NumberOfClusters++
|
||||
movw %bx, %cx # ClusterNumber = NextClusterNumber
|
||||
jmp FatChainLoop
|
||||
ReadClusters:
|
||||
incw %bx
|
||||
popw %ax # ax = StartCluster
|
||||
pushw %bx # StartCluster = NextClusterNumber
|
||||
movw %bx, %cx # ClusterNumber = NextClusterNumber
|
||||
subw $2, %ax # ax = StartCluster - 2
|
||||
xorb %bh, %bh
|
||||
movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
|
||||
mulw %bx # ax = (StartCluster - 2) * SectorsPerCluster
|
||||
addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
|
||||
pushw %ax # save start sector
|
||||
movw %si, %ax # ax = NumberOfClusters
|
||||
mulw %bx # ax = NumberOfClusters * SectorsPerCluster
|
||||
movw %ax, %bx # bx = Number of Sectors
|
||||
popw %ax # ax = Start Sector
|
||||
call ReadBlocks
|
||||
movw $1, %si # NumberOfClusters = 1
|
||||
jmp FatChainLoop
|
||||
FoundLastCluster:
|
||||
popw %cx
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
# ****************************************************************************
|
||||
# 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
|
||||
addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA
|
||||
addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA
|
||||
movl %eax, %esi # esi = Start LBA
|
||||
movw %bx, %cx # cx = Number of blocks to read
|
||||
ReadCylinderLoop:
|
||||
movw $0x7bfc, %bp # bp = 0x7bfc
|
||||
movl %esi, %eax # eax = Start LBA
|
||||
xorl %edx, %edx # edx = 0
|
||||
movzwl (%bp), %ebx # bx = MaxSector
|
||||
divl %ebx # ax = StartLBA / MaxSector
|
||||
incw %dx # dx = (StartLBA % MaxSector) + 1
|
||||
|
||||
movw (%bp), %bx # bx = MaxSector
|
||||
subw %dx, %bx # bx = MaxSector - Sector
|
||||
incw %bx # bx = MaxSector - Sector + 1
|
||||
cmpw %bx, %cx # Compare (Blocks) to (MaxSector - Sector + 1)
|
||||
jg LimitTransfer
|
||||
movw %cx, %bx # bx = Blocks
|
||||
LimitTransfer:
|
||||
pushw %ax # save ax
|
||||
movw %es, %ax # ax = es
|
||||
shrw %ax # ax = Number of blocks into mem system
|
||||
andw $0x7f, %ax # ax = Number of blocks into current seg
|
||||
addw %bx, %ax # ax = End Block number of transfer
|
||||
cmpw $0x80, %ax # See if it crosses a 64K boundry
|
||||
jle NotCrossing64KBoundry # Branch if not crossing 64K boundry
|
||||
subw $0x80, %ax # ax = Number of blocks past 64K boundry
|
||||
subw %ax, %bx # Decrease transfer size by block overage
|
||||
NotCrossing64KBoundry:
|
||||
popw %ax # restore ax
|
||||
|
||||
pushw %cx
|
||||
movb %dl, %cl # cl = (StartLBA % MaxSector) + 1 = Sector
|
||||
xorw %dx, %dx # dx = 0
|
||||
divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder
|
||||
# dx = ax % (MaxHead + 1) = Head
|
||||
|
||||
pushw %bx # Save number of blocks to transfer
|
||||
movb %dl, %dh # dh = Head
|
||||
movw $0x7c00, %bp # bp = 0x7c00
|
||||
movb PhysicalDrive(%bp), %dl # dl = Drive Number
|
||||
movb %al, %ch # ch = Cylinder
|
||||
movb %bl, %al # al = Blocks
|
||||
movb $2, %ah # ah = Function 2
|
||||
movw %di, %bx # es:bx = Buffer address
|
||||
int $0x13
|
||||
jc DiskError
|
||||
popw %bx
|
||||
popw %cx
|
||||
movzwl %bx, %ebx
|
||||
addl %ebx, %esi # StartLBA = StartLBA + NumberOfBlocks
|
||||
subw %bx, %cx # Blocks = Blocks - NumberOfBlocks
|
||||
movw %es, %ax
|
||||
shlw %bx
|
||||
addw %bx, %ax
|
||||
movw %ax, %es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE
|
||||
cmpw $0, %cx
|
||||
jne ReadCylinderLoop
|
||||
popa
|
||||
ret
|
||||
|
||||
DiskError:
|
||||
pushw %cs
|
||||
popw %ds
|
||||
leaw %cs:ErrorString, %si
|
||||
movw $7, %cx
|
||||
jmp PrintStringAndHalt
|
||||
|
||||
PrintStringAndHalt:
|
||||
movw $0xb800, %ax
|
||||
movw %ax, %es
|
||||
movw $160, %di
|
||||
rep
|
||||
movsw
|
||||
Halt:
|
||||
jmp Halt
|
||||
|
||||
ErrorString:
|
||||
.byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!',0x0c
|
||||
|
||||
#.org 0x0242 # For Code size overflow, Modified this just for pass build
|
||||
LBAOffsetForBootSector:
|
||||
.long 0x0
|
||||
|
||||
#.org 0x0227 # For Code size overflow, Modified this just for pass build
|
||||
.word 0xaa55
|
||||
|
||||
#******************************************************************************
|
||||
#******************************************************************************
|
||||
#******************************************************************************
|
||||
|
||||
.equ DELAY_PORT, 0x0ed # Port to use for 1uS delay
|
||||
.equ KBD_CONTROL_PORT, 0x060 # 8042 control port
|
||||
.equ KBD_STATUS_PORT, 0x064 # 8042 status port
|
||||
.equ WRITE_DATA_PORT_CMD, 0x0d1 # 8042 command to write the data port
|
||||
.equ ENABLE_A20_CMD, 0x0df # 8042 command to enable A20
|
||||
|
||||
#.org 0x200
|
||||
jmp start
|
||||
Em64String:
|
||||
.byte 'E', 0x0c, 'm', 0x0c, '6', 0x0c, '4', 0x0c, 'T', 0x0c, ' ', 0x0c, 'U', 0x0c, 'n', 0x0c, 's', 0x0c, 'u', 0x0c, 'p', 0x0c, 'p', 0x0c, 'o', 0x0c, 'r', 0x0c, 't', 0x0c, 'e', 0x0c, 'd', 0x0c, '!', 0x0c
|
||||
|
||||
start:
|
||||
movw %cs, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %ss
|
||||
movw $MyStack, %sp
|
||||
|
||||
# mov ax,0b800h
|
||||
# mov es,ax
|
||||
# mov byte ptr es:[160],'a'
|
||||
# mov ax,cs
|
||||
# mov es,ax
|
||||
|
||||
movl $0, %ebx
|
||||
leal MemoryMap, %edi
|
||||
MemMapLoop:
|
||||
movl $0xe820, %eax
|
||||
movl $20, %ecx
|
||||
movl 0x534d4150, %edx # SMAP
|
||||
int $0x15
|
||||
jc MemMapDone
|
||||
addl $20, %edi
|
||||
cmpl $0, %ebx
|
||||
je MemMapDone
|
||||
jmp MemMapLoop
|
||||
MemMapDone:
|
||||
leal MemoryMap, %eax
|
||||
subl %eax, %edi # Get the address of the memory map
|
||||
movl %edi, MemoryMapSize # Save the size of the memory map
|
||||
|
||||
xorl %ebx, %ebx
|
||||
movw %cs, %bx # BX=segment
|
||||
shll $4, %ebx # BX="linear" address of segment base
|
||||
leal GDT_BASE(%ebx), %eax #
|
||||
movl %eax, (gdtr + 2) #
|
||||
leal IDT_BASE(%ebx), %eax #
|
||||
movl %eax, (idtr + 2) #
|
||||
leal MemoryMapSize(%ebx), %edx #
|
||||
|
||||
addl $0x1000, %ebx # Source of EFI32
|
||||
movl %ebx, JUMP+2
|
||||
addl $0x1000, %ebx
|
||||
movl %ebx, %esi # Source of EFILDR32
|
||||
|
||||
# mov ax,0b800h
|
||||
# mov es,ax
|
||||
# mov byte ptr es:[162],'b'
|
||||
# mov ax,cs
|
||||
# mov es,ax
|
||||
|
||||
#
|
||||
# Enable A20 Gate
|
||||
#
|
||||
|
||||
movw $0x2401, %ax # Enable A20 Gate
|
||||
int $0x15
|
||||
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
|
||||
outw %ax, $DELAY_PORT # Delay 1 uS
|
||||
mov $WRITE_DATA_PORT_CMD, %al # 8042 cmd to write output port
|
||||
out %al, $KBD_STATUS_PORT # Send command to the 8042
|
||||
call Empty8042InputBuffer # Empty the Input Buffer on the 8042 controller
|
||||
jnz Timeout8042 # Jump if the 8042 timed out
|
||||
mov $ENABLE_A20_CMD, %al # gate address bit 20 on
|
||||
out %al, $KBD_CONTROL_PORT # Send command to thre 8042
|
||||
call Empty8042InputBuffer # Empty the Input Buffer on the 8042 controller
|
||||
movw $25, %cx # Delay 25 uS for the command to complete on the 8042
|
||||
Delay25uS:
|
||||
outw %ax, $DELAY_PORT # Delay 1 uS
|
||||
loop Delay25uS
|
||||
Timeout8042:
|
||||
|
||||
|
||||
A20GateEnabled:
|
||||
|
||||
#
|
||||
# DISABLE INTERRUPTS - Entering Protected Mode
|
||||
#
|
||||
|
||||
cli
|
||||
|
||||
# mov ax,0b800h
|
||||
# mov es,ax
|
||||
# mov byte ptr es:[164],'c'
|
||||
# mov ax,cs
|
||||
# mov es,ax
|
||||
|
||||
.byte 0x66
|
||||
lgdt gdtr
|
||||
.byte 0x66
|
||||
lidt idtr
|
||||
|
||||
movl %cr0, %eax
|
||||
orb $1, %al
|
||||
movl %eax, %cr0
|
||||
|
||||
movl $0x008, %eax # Flat data descriptor
|
||||
movl $0x00400000, %ebp # Destination of EFILDR32
|
||||
movl $0x00070000, %ebx # Length of copy
|
||||
|
||||
JUMP:
|
||||
# jmp far 0010:00020000
|
||||
.byte 0x66
|
||||
.byte 0xea
|
||||
.long 0x00020000
|
||||
.word 0x0010
|
||||
|
||||
Empty8042InputBuffer:
|
||||
movw $0, %cx
|
||||
Empty8042Loop:
|
||||
outw %ax, $DELAY_PORT # Delay 1us
|
||||
in $KBD_STATUS_PORT, %al # Read the 8042 Status Port
|
||||
andb $0x2, %al # Check the Input Buffer Full Flag
|
||||
loopnz Empty8042Loop # Loop until the input buffer is empty or a timout of 65536 uS
|
||||
ret
|
||||
|
||||
##############################################################################
|
||||
# data
|
||||
##############################################################################
|
||||
|
||||
.align 0x2
|
||||
|
||||
gdtr: .long GDT_END - GDT_BASE - 1 # GDT limit
|
||||
.long 0 # (GDT base gets set above)
|
||||
##############################################################################
|
||||
# global descriptor table (GDT)
|
||||
##############################################################################
|
||||
|
||||
.align 0x2
|
||||
|
||||
GDT_BASE:
|
||||
# null descriptor
|
||||
.equ NULL_SEL, .-GDT_BASE
|
||||
.word 0 # limit 15:0
|
||||
.word 0 # base 15:0
|
||||
.byte 0 # base 23:16
|
||||
.byte 0 # type
|
||||
.byte 0 # limit 19:16, flags
|
||||
.byte 0 # base 31:24
|
||||
|
||||
# linear data segment descriptor
|
||||
.equ LINEAR_SEL, .-GDT_BASE
|
||||
.word 0xFFFF # limit 0xFFFFF
|
||||
.word 0 # base 0
|
||||
.byte 0
|
||||
.byte 0x92 # present, ring 0, data, expand-up, writable
|
||||
.byte 0xCF # page-granular, 32-bit
|
||||
.byte 0
|
||||
|
||||
# linear code segment descriptor
|
||||
.equ LINEAR_CODE_SEL, .-GDT_BASE
|
||||
.word 0xFFFF # limit 0xFFFFF
|
||||
.word 0 # base 0
|
||||
.byte 0
|
||||
.byte 0x9A # present, ring 0, data, expand-up, writable
|
||||
.byte 0xCF # page-granular, 32-bit
|
||||
.byte 0
|
||||
|
||||
# system data segment descriptor
|
||||
.equ SYS_DATA_SEL, .-GDT_BASE
|
||||
.word 0xFFFF # limit 0xFFFFF
|
||||
.word 0 # base 0
|
||||
.byte 0
|
||||
.byte 0x92 # present, ring 0, data, expand-up, writable
|
||||
.byte 0xCF # page-granular, 32-bit
|
||||
.byte 0
|
||||
|
||||
# system code segment descriptor
|
||||
.equ SYS_CODE_SEL, .-GDT_BASE
|
||||
.word 0xFFFF # limit 0xFFFFF
|
||||
.word 0 # base 0
|
||||
.byte 0
|
||||
.byte 0x9A # present, ring 0, data, expand-up, writable
|
||||
.byte 0xCF # page-granular, 32-bit
|
||||
.byte 0
|
||||
|
||||
# spare segment descriptor
|
||||
.equ SPARE3_SEL, .-GDT_BASE
|
||||
.word 0 # limit 0xFFFFF
|
||||
.word 0 # base 0
|
||||
.byte 0
|
||||
.byte 0 # present, ring 0, data, expand-up, writable
|
||||
.byte 0 # page-granular, 32-bit
|
||||
.byte 0
|
||||
|
||||
# spare segment descriptor
|
||||
.equ SPARE4_SEL, .-GDT_BASE
|
||||
.word 0 # limit 0xFFFFF
|
||||
.word 0 # base 0
|
||||
.byte 0
|
||||
.byte 0 # present, ring 0, data, expand-up, writable
|
||||
.byte 0 # page-granular, 32-bit
|
||||
.byte 0
|
||||
|
||||
# spare segment descriptor
|
||||
.equ SPARE5_SEL, .-GDT_BASE
|
||||
.word 0 # limit 0xFFFFF
|
||||
.word 0 # base 0
|
||||
.byte 0
|
||||
.byte 0 # present, ring 0, data, expand-up, writable
|
||||
.byte 0 # page-granular, 32-bit
|
||||
.byte 0
|
||||
|
||||
GDT_END:
|
||||
|
||||
.align 0x2
|
||||
|
||||
|
||||
|
||||
idtr: .long IDT_END - IDT_BASE - 1 # IDT limit
|
||||
.long 0 # (IDT base gets set above)
|
||||
##############################################################################
|
||||
# interrupt descriptor table (IDT)
|
||||
#
|
||||
# Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
|
||||
# mappings. This implementation only uses the system timer and all other
|
||||
# IRQs will remain masked. The descriptors for vectors 33+ are provided
|
||||
# for convenience.
|
||||
##############################################################################
|
||||
|
||||
#idt_tag db "IDT",0
|
||||
.align 0x2
|
||||
|
||||
IDT_BASE:
|
||||
# divide by zero (INT 0)
|
||||
.equ DIV_ZERO_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# debug exception (INT 1)
|
||||
.equ DEBUG_EXCEPT_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# NMI (INT 2)
|
||||
.equ NMI_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# soft breakpoint (INT 3)
|
||||
.equ BREAKPOINT_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# overflow (INT 4)
|
||||
.equ OVERFLOW_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# bounds check (INT 5)
|
||||
.equ BOUNDS_CHECK_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# invalid opcode (INT 6)
|
||||
.equ INVALID_OPCODE_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# device not available (INT 7)
|
||||
.equ DEV_NOT_AVAIL_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# double fault (INT 8)
|
||||
.equ DOUBLE_FAULT_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# Coprocessor segment overrun - reserved (INT 9)
|
||||
.equ RSVD_INTR_SEL1, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# invalid TSS (INT 0x0a)
|
||||
.equ INVALID_TSS_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# segment not present (INT 0x0b)
|
||||
.equ SEG_NOT_PRESENT_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# stack fault (INT 0x0c)
|
||||
.equ STACK_FAULT_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# general protection (INT 0x0d)
|
||||
.equ GP_FAULT_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# page fault (INT 0x0e)
|
||||
.equ PAGE_FAULT_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# Intel reserved - do not use (INT 0x0f)
|
||||
.equ RSVD_INTR_SEL2, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# floating point error (INT 0x10)
|
||||
.equ FLT_POINT_ERR_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# alignment check (INT 0x11)
|
||||
.equ ALIGNMENT_CHECK_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# machine check (INT 0x12)
|
||||
.equ MACHINE_CHECK_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# SIMD floating-point exception (INT 0x13)
|
||||
.equ SIMD_EXCEPTION_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
|
||||
.fill 85 * 8, 1, 0 # db (85 * 8) dup(0)
|
||||
|
||||
# IRQ 0 (System timer) - (INT 0x68)
|
||||
.equ IRQ0_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 1 (8042 Keyboard controller) - (INT 0x69)
|
||||
.equ IRQ1_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 0x6a)
|
||||
.equ IRQ2_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 3 (COM 2) - (INT 0x6b)
|
||||
.equ IRQ3_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 4 (COM 1) - (INT 0x6c)
|
||||
.equ IRQ4_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 5 (LPT 2) - (INT 0x6d)
|
||||
.equ IRQ5_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 6 (Floppy controller) - (INT 0x6e)
|
||||
.equ IRQ6_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 7 (LPT 1) - (INT 0x6f)
|
||||
.equ IRQ7_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 8 (RTC Alarm) - (INT 0x70)
|
||||
.equ IRQ8_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 9 - (INT 0x71)
|
||||
.equ IRQ9_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 10 - (INT 0x72)
|
||||
.equ IRQ10_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 11 - (INT 0x73)
|
||||
.equ IRQ11_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 12 (PS/2 mouse) - (INT 0x74)
|
||||
.equ IRQ12_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 13 (Floating point error) - (INT 0x75)
|
||||
.equ IRQ13_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 14 (Secondary IDE) - (INT 0x76)
|
||||
.equ IRQ14_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
# IRQ 15 (Primary IDE) - (INT 0x77)
|
||||
.equ IRQ15_SEL, .-IDT_BASE
|
||||
.word 0 # offset 15:0
|
||||
.long SYS_CODE_SEL # selector 15:0
|
||||
.byte 0 # 0 for interrupt gate
|
||||
.byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
|
||||
.word 0 # offset 31:16
|
||||
|
||||
IDT_END:
|
||||
|
||||
.align 0x2
|
||||
|
||||
MemoryMapSize: .long 0
|
||||
MemoryMap: .long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0
|
||||
|
||||
.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
|
||||
.org 0x0fe0
|
||||
MyStack:
|
||||
# below is the pieces of the IVT that is used to redirect INT 68h - 6fh
|
||||
# back to INT 08h - 0fh when in real mode... It is 'org'ed to a
|
||||
# known low address (20f00) so it can be set up by PlMapIrqToVect in
|
||||
# 8259.c
|
||||
|
||||
int $8
|
||||
iret
|
||||
|
||||
int $9
|
||||
iret
|
||||
|
||||
int $10
|
||||
iret
|
||||
|
||||
int $11
|
||||
iret
|
||||
|
||||
int $12
|
||||
iret
|
||||
|
||||
int $13
|
||||
iret
|
||||
|
||||
int $14
|
||||
iret
|
||||
|
||||
int $15
|
||||
iret
|
||||
|
||||
|
||||
.org 0x0ffe
|
||||
BlockSignature:
|
||||
.word 0xaa55
|
||||
|
||||
|
Loading…
Reference in New Issue