Porting Duet module from EDKI to EDKII

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5076 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
klu2 2008-04-17 05:48:13 +00:00
parent fcf03596d1
commit c69dd9dfad
77 changed files with 26415 additions and 13 deletions

View File

@ -0,0 +1,30 @@
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = BootSector
FILE_GUID = A36495C1-C205-414e-B71F-4BE3476D699C
MODULE_TYPE = USER_DEFINED
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
[Packages]
MdePkg/MdePkg.dec
DuetPkg/DuetPkg.dec
[Sources]
bootsect.asm
bs16.asm
bs32.asm
Gpt.asm
Mbr.asm
Start.asm
Start16.asm
Start32.asm
Efi32.asm
[BuildOptions.common]
#MSFT:*_*_IA32_DLINK_FLAGS = /out:"$(BIN_DIR)\SecMain.exe" /base:0x10000000 /pdb:"$(BIN_DIR)\SecMain.pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib
MSFT:*_*_IA32_CC_FLAGS = /nologo /W4 /WX /Gy /c /D UNICODE /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
MSFT:*_*_IA32_PP_FLAGS = /nologo /E /TC /FI$(DEST_DIR_DEBUG)/AutoGen.h
MSFT:*_*_IA32_ASM_FLAGS = /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi
MSFT:*_*_IA32_ASMLINK_FLAGS = /link /nologo /tiny

View File

@ -0,0 +1,26 @@
IA32
====
FAT12 FAT16 FAT32
bootsect.asm bs16.asm bs32.asm
start.asm start16.asm start32.asm
\ | /
\ | /
efi32.asm
X64
===
FAT12 FAT16 FAT32
bootsect.asm bs16.asm bs32.asm
start64.asm st16_64.asm st32_64.asm
\ | /
\ | /
efi64.asm
MBR
===
Mbr.asm
GPT
===
Gpt.asm

294
DuetPkg/BootSector/Gpt.asm Normal file
View File

@ -0,0 +1,294 @@
;------------------------------------------------------------------------------
;*
;* 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.
;*
;* gpt.asm
;*
;* Abstract:
;*
;------------------------------------------------------------------------------
.model small
; .dosseg
.stack
.486p
.code
BLOCK_SIZE EQU 0200h
BLOCK_MASK EQU 01ffh
BLOCK_SHIFT EQU 9
; ****************************************************************************
; Code loaded by BIOS at 0x0000:0x7C00
; ****************************************************************************
org 0h
Start:
; ****************************************************************************
; Start Print
; ****************************************************************************
mov ax,0b800h
mov es,ax
mov ax, 07c0h
mov ds, ax
lea si, cs:[StartString]
mov cx, 10
mov di, 160
rep movsw
; ****************************************************************************
; Print over
; ****************************************************************************
; ****************************************************************************
; Initialize segment registers and copy code at 0x0000:0x7c00 to 0x0000:0x0600
; ****************************************************************************
xor ax, ax ; AX = 0x0000
mov bx, 07c00h ; BX = 0x7C00
mov bp, 0600h ; BP = 0x0600
mov si, OFFSET RelocatedStart ; SI = Offset(RelocatedStart)
mov cx, 0200h ; CX = 0x0200
sub cx, si ; CS = 0x0200 - Offset(RelocatedStart)
lea di, [bp+si] ; DI = 0x0600 + Offset(RelocatedStart)
lea si, [bx+si] ; BX = 0x7C00 + Offset(RelocatedStart)
mov ss, ax ; SS = 0x0000
mov sp, bx ; SP = 0x7C00
mov es,ax ; ES = 0x0000
mov ds,ax ; DS = 0x0000
push ax ; PUSH 0x0000
push di ; PUSH 0x0600 + Offset(RelocatedStart)
cld ; Clear the direction flag
rep movsb ; Copy 0x0200 bytes from 0x7C00 to 0x0600
retf ; JMP 0x0000:0x0600 + Offset(RelocatedStart)
; ****************************************************************************
; Code relocated to 0x0000:0x0600
; ****************************************************************************
RelocatedStart:
; ****************************************************************************
; Get Driver Parameters to 0x0000:0x7BFC
; ****************************************************************************
xor ax,ax ; ax = 0
mov ss,ax ; ss = 0
add ax,1000h
mov ds,ax
mov sp,07c00h ; sp = 0x7c00
mov bp,sp ; bp = 0x7c00
mov ah,8 ; ah = 8 - Get Drive Parameters Function
mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
int 13h ; Get Drive Parameters
xor ax,ax ; ax = 0
mov al,dh ; al = dh
inc al ; MaxHead = al + 1
push ax ; 0000:7bfe = MaxHead
mov al,cl ; al = cl
and al,03fh ; MaxSector = al & 0x3f
push ax ; 0000:7bfc = MaxSector
; ****************************************************************************
; Read GPT Header from hard disk to 0x0000:0x0800
; ****************************************************************************
xor ax, ax
mov es, ax ; Read to 0x0000:0x0800
mov di, 0800h ; Read to 0x0000:0x0800
mov eax, 1 ; Read LBA #1
mov edx, 0 ; Read LBA #1
mov bx, 1 ; Read 1 Block
push es
call ReadBlocks
pop es
; ****************************************************************************
; Read Target GPT Entry from hard disk to 0x0000:0x0A00
; ****************************************************************************
cmp dword ptr es:[di], 020494645h ; Check for "EFI "
jne BadGpt
cmp dword ptr es:[di + 4], 054524150h ; Check for "PART"
jne BadGpt
cmp dword ptr es:[di + 8], 000010000h ; Check Revision - 0x10000
jne BadGpt
mov eax, dword ptr es:[di + 84] ; EAX = SizeOfPartitionEntry
mul byte ptr [bp+GptPartitionIndicator] ; EAX = SizeOfPartitionEntry * GptPartitionIndicator
mov edx, eax ; EDX = SizeOfPartitionEntry * GptPartitionIndicator
shr eax, BLOCK_SHIFT ; EAX = (SizeOfPartitionEntry * GptPartitionIndicator) / BLOCK_SIZE
and edx, BLOCK_MASK ; EDX = Targer PartitionEntryLBA Offset
; = (SizeOfPartitionEntry * GptPartitionIndicator) % BLOCK_SIZE
push edx
mov ecx, dword ptr es:[di + 72] ; ECX = PartitionEntryLBA (Low)
mov ebx, dword ptr es:[di + 76] ; EBX = PartitionEntryLBA (High)
add eax, ecx ; EAX = Target PartitionEntryLBA (Low)
; = (PartitionEntryLBA +
; (SizeOfPartitionEntry * GptPartitionIndicator) / BLOCK_SIZE)
adc edx, ebx ; EDX = Target PartitionEntryLBA (High)
mov di, 0A00h ; Read to 0x0000:0x0A00
mov bx, 1 ; Read 1 Block
push es
call ReadBlocks
pop es
; ****************************************************************************
; Read Target DBR from hard disk to 0x0000:0x7C00
; ****************************************************************************
pop edx ; EDX = (SizeOfPartitionEntry * GptPartitionIndicator) % BLOCK_SIZE
add di, dx ; DI = Targer PartitionEntryLBA Offset
cmp dword ptr es:[di], 0C12A7328h ; Check for EFI System Partition "C12A7328-F81F-11d2-BA4B-00A0C93EC93B"
jne BadGpt
cmp dword ptr es:[di + 4], 011d2F81Fh ;
jne BadGpt
cmp dword ptr es:[di + 8], 0A0004BBAh ;
jne BadGpt
cmp dword ptr es:[di + 0ch], 03BC93EC9h ;
jne BadGpt
mov eax, dword ptr es:[di + 32] ; EAX = StartingLBA (Low)
mov edx, dword ptr es:[di + 36] ; EDX = StartingLBA (High)
mov di, 07C00h ; Read to 0x0000:0x7C00
mov bx, 1 ; Read 1 Block
call ReadBlocks
; ****************************************************************************
; Transfer control to BootSector - Jump to 0x0000:0x7C00
; ****************************************************************************
xor ax, ax
push ax ; PUSH 0x0000
mov di, 07c00h
push di ; PUSH 0x7C00
retf ; JMP 0x0000:0x7C00
; ****************************************************************************
; ReadBlocks - Reads a set of blocks from a block device
;
; EDX:EAX = Start LBA
; BX = Number of Blocks to Read (must < 127)
; ES:DI = Buffer to store sectors read from disk
; ****************************************************************************
; si = DiskAddressPacket
ReadBlocks:
pushad
push ds
xor cx, cx
mov ds, cx
mov bp, 0600h ; bp = 0x600
lea si, [bp + OFFSET AddressPacket] ; DS:SI = Disk Address Packet
mov BYTE PTR ds:[si+2],bl ; 02 = Number Of Block transfered
mov WORD PTR ds:[si+4],di ; 04 = Transfer Buffer Offset
mov WORD PTR ds:[si+6],es ; 06 = Transfer Buffer Segment
mov DWORD PTR ds:[si+8],eax ; 08 = Starting LBA (Low)
mov DWORD PTR ds:[si+0ch],edx ; 0C = Starting LBA (High)
mov ah, 42h ; ah = Function 42
mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
int 13h
jc BadGpt
pop ds
popad
ret
; ****************************************************************************
; Address Packet used by ReadBlocks
; ****************************************************************************
AddressPacket:
db 10h ; Size of address packet
db 00h ; Reserved. Must be 0
db 01h ; Read blocks at a time (To be fixed each times)
db 00h ; Reserved. Must be 0
dw 0000h ; Destination Address offset (To be fixed each times)
dw 0000h ; Destination Address segment (To be fixed each times)
AddressPacketLba:
dd 0h, 0h ; Start LBA (To be fixed each times)
AddressPacketEnd:
; ****************************************************************************
; ERROR Condition:
; ****************************************************************************
BadGpt:
mov ax,0b800h
mov es,ax
mov ax, 060h
mov ds, ax
lea si, cs:[ErrorString]
mov cx, 10
mov di, 320
rep movsw
Halt:
jmp Halt
StartString:
db 'G', 0ch, 'P', 0ch, 'T', 0ch, ' ', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
ErrorString:
db 'G', 0ch, 'P', 0ch, 'T', 0ch, ' ', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
; ****************************************************************************
; PhysicalDrive - Used to indicate which disk to be boot
; Can be patched by tool
; ****************************************************************************
org 01B6h
PhysicalDrive db 80h
; ****************************************************************************
; GptPartitionIndicator - Used to indicate which GPT partition to be boot
; Can be patched by tool
; ****************************************************************************
org 01B7h
GptPartitionIndicator db 0
; ****************************************************************************
; Unique MBR signature
; ****************************************************************************
org 01B8h
db 'DUET'
; ****************************************************************************
; Unknown
; ****************************************************************************
org 01BCh
dw 0
; ****************************************************************************
; PMBR Entry - Can be patched by tool
; ****************************************************************************
org 01BEh
db 0 ; Boot Indicator
db 0ffh ; Start Header
db 0ffh ; Start Sector
db 0ffh ; Start Track
db 0eeh ; OS Type
db 0ffh ; End Header
db 0ffh ; End Sector
db 0ffh ; End Track
dd 1 ; Starting LBA
dd 0FFFFFFFFh ; End LBA
org 01CEh
dd 0, 0, 0, 0
org 01DEh
dd 0, 0, 0, 0
org 01EEh
dd 0, 0, 0, 0
; ****************************************************************************
; Sector Signature
; ****************************************************************************
org 01FEh
SectorSignature:
dw 0aa55h ; Boot Sector Signature
end

276
DuetPkg/BootSector/Makefile Normal file
View File

@ -0,0 +1,276 @@
#
# Platform Macro Definition
#
PLATFORM_NAME = DuetPkg
PLATFORM_GUID = 199E24E0-0989-42aa-87F2-611A8C397E72
PLATFORM_VERSION = 0.3
PLATFORM_RELATIVE_DIR = DuetPkg
PLATFORM_DIR = $(WORKSPACE)\DuetPkg
PLATFORM_OUTPUT_DIR = Build\DuetPkg
#
# Module Macro Definition
#
MODULE_NAME = BootSector
MODULE_GUID = 2410F0DF-D915-4137-BD04-AAB6BA4C50E0
MODULE_VERSION = 1.0
MODULE_TYPE = USER_DEFINED
MODULE_FILE_BASE_NAME = BootSector
BASE_NAME = $(MODULE_NAME)
MODULE_RELATIVE_DIR = DuetPkg\BootSector
MODULE_DIR = $(WORKSPACE)\DuetPkg\BootSector
#
# Build Configuration Macro Definition
#
ARCH = IA32
TOOLCHAIN_TAG = MYTOOLS
TARGET = DEBUG
BASETOOLS_DIR=m:\tree\working\BaseTools\Bin\Win32
#
# Build Directory Macro Definition
#
# PLATFORM_BUILD_DIR = m:\tree\working\Build\DuetPkg\DEBUG_MYTOOLS
BUILD_DIR = $(WORKSPACE)\Build\DuetPkg\DEBUG_MYTOOLS
BIN_DIR = $(BUILD_DIR)\IA32
LIB_DIR = $(BIN_DIR)
MODULE_BUILD_DIR = $(BUILD_DIR)\IA32\DuetPkg\BootSector\BootSector
OUTPUT_DIR = $(MODULE_BUILD_DIR)\OUTPUT
DEBUG_DIR = $(MODULE_BUILD_DIR)\DEBUG
DEST_DIR_OUTPUT = $(OUTPUT_DIR)
DEST_DIR_DEBUG = $(DEBUG_DIR)
#
# Default Tools Flags Macro Definition (from tools_def.txt by default)
#
DEFAULT_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
DEFAULT_SLINK_FLAGS = /nologo /LTCG
DEFAULT_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs8192 /Gy /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
DEFAULT_APP_FLAGS = /nologo /E /TC
DEFAULT_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FIAutoGen.h
DEFAULT_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4086 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /MACHINE:I386 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
DEFAULT_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
DEFAULT_TIANO_FLAGS =
DEFAULT_MAKE_FLAGS = /nologo
DEFAULT_ASMLINK_FLAGS = /nologo /tiny
DEFAULT_ASL_FLAGS =
#
# Platform Tools Flags Macro Definition (from platform description file)
#
PLATFORM_PP_FLAGS =
PLATFORM_SLINK_FLAGS =
PLATFORM_CC_FLAGS =
PLATFORM_APP_FLAGS =
PLATFORM_VFRPP_FLAGS =
PLATFORM_DLINK_FLAGS =
PLATFORM_ASM_FLAGS =
PLATFORM_TIANO_FLAGS =
PLATFORM_MAKE_FLAGS =
PLATFORM_ASMLINK_FLAGS =
PLATFORM_ASL_FLAGS =
#
# Module Tools Flags Macro Definition (from platform/module description file)
#
MODULE_PP_FLAGS =
MODULE_SLINK_FLAGS =
MODULE_CC_FLAGS =
MODULE_APP_FLAGS =
MODULE_VFRPP_FLAGS =
MODULE_DLINK_FLAGS =
MODULE_ASM_FLAGS =
MODULE_TIANO_FLAGS =
MODULE_MAKE_FLAGS =
MODULE_ASMLINK_FLAGS =
MODULE_ASL_FLAGS =
#
# Tools Flag Macro
#
PP_FLAGS = $(DEFAULT_PP_FLAGS) $(PLATFORM_PP_FLAGS) $(MODULE_PP_FLAGS)
SLINK_FLAGS = $(DEFAULT_SLINK_FLAGS) $(PLATFORM_SLINK_FLAGS) $(MODULE_SLINK_FLAGS)
CC_FLAGS = $(DEFAULT_CC_FLAGS) $(PLATFORM_CC_FLAGS) $(MODULE_CC_FLAGS)
APP_FLAGS = $(DEFAULT_APP_FLAGS) $(PLATFORM_APP_FLAGS) $(MODULE_APP_FLAGS)
VFRPP_FLAGS = $(DEFAULT_VFRPP_FLAGS) $(PLATFORM_VFRPP_FLAGS) $(MODULE_VFRPP_FLAGS)
DLINK_FLAGS = $(DEFAULT_DLINK_FLAGS) $(PLATFORM_DLINK_FLAGS) $(MODULE_DLINK_FLAGS)
ASM_FLAGS = $(DEFAULT_ASM_FLAGS) $(PLATFORM_ASM_FLAGS) $(MODULE_ASM_FLAGS)
TIANO_FLAGS = $(DEFAULT_TIANO_FLAGS) $(PLATFORM_TIANO_FLAGS) $(MODULE_TIANO_FLAGS)
MAKE_FLAGS = $(DEFAULT_MAKE_FLAGS) $(PLATFORM_MAKE_FLAGS) $(MODULE_MAKE_FLAGS)
ASMLINK_FLAGS = $(DEFAULT_ASMLINK_FLAGS) $(PLATFORM_ASMLINK_FLAGS) $(MODULE_ASMLINK_FLAGS)
ASL_FLAGS = $(DEFAULT_ASL_FLAGS) $(PLATFORM_ASL_FLAGS) $(MODULE_ASL_FLAGS)
#
# Tools Path Macro
#
PP = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
SLINK = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\lib.exe
CC = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
APP = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
VFRPP = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
DLINK = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\link.exe
ASM = C:\WINDDK\3790.1830\bin\x86\ml.exe
TIANO = TianoCompress.exe
MAKE = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\nmake.exe
#ASMLINK = C:\WINDDK\3790.1830\bin\bin16\link.exe
ASMLINK = C:\WINDDK\3790.1830\bin\bin16\link16.exe
ASL = C:\ASL\iasl.exe
MAKE_FILE = $(MODULE_BUILD_DIR)\Makefile
#
# Shell Command Macro
#
RD = rmdir /s /q
RM = del /f /q
MD = mkdir
CP = copy /y
MV = move /y
#
# Build Macro
#
ASSEMBLY_CODE_FILE_LIST = $(MODULE_DIR)\bootsect.asm \
$(MODULE_DIR)\bs16.asm \
$(MODULE_DIR)\bs32.asm \
$(MODULE_DIR)\efi32.asm \
$(MODULE_DIR)\Gpt.asm \
$(MODULE_DIR)\Mbr.asm \
$(MODULE_DIR)\start.asm \
$(MODULE_DIR)\start16.asm \
$(MODULE_DIR)\start32.asm
TARGET_FILES = $(OUTPUT_DIR)\bootsect.com \
$(OUTPUT_DIR)\bs16.com \
$(OUTPUT_DIR)\bs32.com \
$(OUTPUT_DIR)\Gpt.com \
$(OUTPUT_DIR)\Mbr.com \
$(OUTPUT_DIR)\Start.com \
$(OUTPUT_DIR)\Start16.com \
$(OUTPUT_DIR)\Start32.com \
$(OUTPUT_DIR)\efi32.com2
INC =
#OBJECTS =
LIBS =
COMMON_DEPS =
all: init $(TARGET_FILES) loader
init:
if not exist $(OUTPUT_DIR) mkdir $(OUTPUT_DIR)
if not exist $(DEBUG_DIR) mkdir $(DEBUG_DIR)
#=============
$(OUTPUT_DIR)\bootsect.obj:$(MODULE_DIR)\bootsect.asm
$(ASM) /c /omf /Fo"$(OUTPUT_DIR)\bootsect.obj" /FR"$(OUTPUT_DIR)\bootsect.txt" "$(MODULE_DIR)\bootsect.asm"
$(OUTPUT_DIR)\bootsect.com:$(OUTPUT_DIR)\bootsect.obj
"$(ASMLINK)" /tiny $(OUTPUT_DIR)\bootsect.obj,$(OUTPUT_DIR)\bootsect.com,$(OUTPUT_DIR)\bootsect.map,,,
#=============
$(OUTPUT_DIR)\bs16.obj:$(MODULE_DIR)\bs16.asm
$(ASM) /c /omf /Fo"$(OUTPUT_DIR)\bs16.obj" "$(MODULE_DIR)\bs16.asm"
$(OUTPUT_DIR)\bs16.com:$(OUTPUT_DIR)\bs16.obj
"$(ASMLINK)" /tiny $(OUTPUT_DIR)\bs16.obj,$(OUTPUT_DIR)\bs16.com,$(OUTPUT_DIR)\bs16.map,,,
#=============
$(OUTPUT_DIR)\bs32.obj:$(MODULE_DIR)\bs32.asm
$(ASM) /c /omf /Fo"$(OUTPUT_DIR)\bs32.obj" "$(MODULE_DIR)\bs32.asm"
$(OUTPUT_DIR)\bs32.com:$(OUTPUT_DIR)\bs32.obj
"$(ASMLINK)" /tiny $(OUTPUT_DIR)\bs32.obj,$(OUTPUT_DIR)\bs32.com,$(OUTPUT_DIR)\bs32.map,,,
#=============
$(OUTPUT_DIR)\Gpt.obj:$(MODULE_DIR)\Gpt.asm
$(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Gpt.obj" "$(MODULE_DIR)\Gpt.asm"
$(OUTPUT_DIR)\Gpt.com:$(OUTPUT_DIR)\Gpt.obj
"$(ASMLINK)" /tiny $(OUTPUT_DIR)\Gpt.obj,$(OUTPUT_DIR)\Gpt.com,$(OUTPUT_DIR)\Gpt.map,,,
#=============
$(OUTPUT_DIR)\Mbr.obj:$(MODULE_DIR)\Mbr.asm
$(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Mbr.obj" "$(MODULE_DIR)\Mbr.asm"
$(OUTPUT_DIR)\Mbr.com:$(OUTPUT_DIR)\Mbr.obj
"$(ASMLINK)" /tiny $(OUTPUT_DIR)\Mbr.obj,$(OUTPUT_DIR)\Mbr.com,$(OUTPUT_DIR)\Mbr.map,,,
#============
$(OUTPUT_DIR)\Start.obj:$(MODULE_DIR)\Start.asm
$(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Start.obj" "$(MODULE_DIR)\Start.asm"
$(OUTPUT_DIR)\Start.com:$(OUTPUT_DIR)\Start.obj
"$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start.obj,$(OUTPUT_DIR)\Start.com,$(OUTPUT_DIR)\Start.map,,,
#=============
$(OUTPUT_DIR)\Start16.obj:$(MODULE_DIR)\Start16.asm
$(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Start16.obj" "$(MODULE_DIR)\Start16.asm"
$(OUTPUT_DIR)\Start16.com:$(OUTPUT_DIR)\Start16.obj
"$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start16.obj,$(OUTPUT_DIR)\Start16.com,$(OUTPUT_DIR)\Start16.map,,,
#=============
$(OUTPUT_DIR)\Start32.obj:$(MODULE_DIR)\Start32.asm
$(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Start32.obj" "$(MODULE_DIR)\Start32.asm"
$(OUTPUT_DIR)\Start32.com:$(OUTPUT_DIR)\Start32.obj
"$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start32.obj,$(OUTPUT_DIR)\Start32.com,$(OUTPUT_DIR)\Start32.map,,,
#=============
$(OUTPUT_DIR)\efi32.obj:$(MODULE_DIR)\efi32.asm
$(ASM) /c /omf /Fo"$(OUTPUT_DIR)\efi32.obj" "$(MODULE_DIR)\efi32.asm"
$(OUTPUT_DIR)\efi32.com:$(OUTPUT_DIR)\efi32.obj
"$(ASMLINK)" /tiny $(OUTPUT_DIR)\efi32.obj,$(OUTPUT_DIR)\efi32.com,$(OUTPUT_DIR)\efi32.map,,,
#=============
$(OUTPUT_DIR)\efi32.com2:$(OUTPUT_DIR)\efi32.com
$(BASETOOLS_DIR)\Split.exe -f $(OUTPUT_DIR)\efi32.com -t $(OUTPUT_DIR)\efi32.com2 -s 135168
#
# clean all generated files
#
loader:$(BUILD_DIR)\FV\Efildr
$(BUILD_DIR)\FV\DUETEFIMAINFV.z:$(BUILD_DIR)\FV\DUETEFIMAINFV.Fv
$(BASETOOLS_DIR)\TianoCompress -e -o $(BUILD_DIR)\FV\DUETEFIMAINFV.z $(BUILD_DIR)\FV\DUETEFIMAINFV.Fv
$(BUILD_DIR)\FV\DxeMain.z:$(BUILD_DIR)\IA32\DxeMain.efi
$(BASETOOLS_DIR)\TianoCompress -e -o $(BUILD_DIR)\FV\DxeMain.z $(BUILD_DIR)\IA32\DxeMain.efi
$(BUILD_DIR)\FV\DxeIpl.z:$(BUILD_DIR)\IA32\DxeIpl.efi
$(BASETOOLS_DIR)\TianoCompress -e -o $(BUILD_DIR)\FV\DxeIpl.z $(BUILD_DIR)\IA32\DxeIpl.efi
$(BUILD_DIR)\FV\Efildr32:$(BUILD_DIR)\IA32\EfiLoader.efi $(BUILD_DIR)\FV\DxeIpl.z $(BUILD_DIR)\FV\DUETEFIMAINFV.z
$(BASETOOLS_DIR)\EfiLdrImage.exe -o $(BUILD_DIR)\FV\Efildr32 $(BUILD_DIR)\IA32\EfiLoader.efi $(BUILD_DIR)\FV\DxeIpl.z $(BUILD_DIR)\FV\DUETEFIMAINFV.z
$(BUILD_DIR)\FV\Efildr:$(OUTPUT_DIR)\Start.com $(OUTPUT_DIR)\Efi32.com2 $(BUILD_DIR)\FV\Efildr32
copy /b $(OUTPUT_DIR)\BootSect.com+$(OUTPUT_DIR)\Efi32.com2+$(BUILD_DIR)\FV\Efildr32 $(BUILD_DIR)\FV\Efildr
clean:
if exist $(DEBUG_DIR) rmdir /s /q $(DEBUG_DIR)
if exist $(OUTPUT_DIR) rmdir /s /q $(OUTPUT_DIR)

261
DuetPkg/BootSector/Mbr.asm Normal file
View File

@ -0,0 +1,261 @@
;------------------------------------------------------------------------------
;*
;* 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:
;*
;------------------------------------------------------------------------------
.model small
; .dosseg
.stack
.486p
.code
BLOCK_SIZE EQU 0200h
BLOCK_MASK EQU 01ffh
BLOCK_SHIFT EQU 9
; ****************************************************************************
; Code loaded by BIOS at 0x0000:0x7C00
; ****************************************************************************
org 0h
Start:
; ****************************************************************************
; Start Print
; ****************************************************************************
mov ax,0b800h
mov es,ax
mov ax, 07c0h
mov ds, ax
lea si, cs:[StartString]
mov cx, 10
mov di, 160
rep movsw
; ****************************************************************************
; Print over
; ****************************************************************************
; ****************************************************************************
; Initialize segment registers and copy code at 0x0000:0x7c00 to 0x0000:0x0600
; ****************************************************************************
xor ax, ax ; AX = 0x0000
mov bx, 07c00h ; BX = 0x7C00
mov bp, 0600h ; BP = 0x0600
mov si, OFFSET RelocatedStart ; SI = Offset(RelocatedStart)
mov cx, 0200h ; CX = 0x0200
sub cx, si ; CS = 0x0200 - Offset(RelocatedStart)
lea di, [bp+si] ; DI = 0x0600 + Offset(RelocatedStart)
lea si, [bx+si] ; BX = 0x7C00 + Offset(RelocatedStart)
mov ss, ax ; SS = 0x0000
mov sp, bx ; SP = 0x7C00
mov es,ax ; ES = 0x0000
mov ds,ax ; DS = 0x0000
push ax ; PUSH 0x0000
push di ; PUSH 0x0600 + Offset(RelocatedStart)
cld ; Clear the direction flag
rep movsb ; Copy 0x0200 bytes from 0x7C00 to 0x0600
retf ; JMP 0x0000:0x0600 + Offset(RelocatedStart)
; ****************************************************************************
; Code relocated to 0x0000:0x0600
; ****************************************************************************
RelocatedStart:
; ****************************************************************************
; Get Driver Parameters to 0x0000:0x7BFC
; ****************************************************************************
xor ax,ax ; AX = 0
mov ss,ax ; SS = 0
add ax,1000h
mov ds,ax
mov sp,07c00h ; SP = 0x7c00
mov bp,sp ; BP = 0x7c00
mov ah,8 ; AH = 8 - Get Drive Parameters Function
mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
int 13h ; Get Drive Parameters
xor ax,ax ; AX = 0
mov al,dh ; AL = DH
inc al ; MaxHead = AL + 1
push ax ; 0000:7bfe = MaxHead
mov al,cl ; AL = CL
and al,03fh ; MaxSector = AL & 0x3f
push ax ; 0000:7bfc = MaxSector
; ****************************************************************************
; Read Target DBR from hard disk to 0x0000:0x7C00
; ****************************************************************************
xor ax, ax
mov al, byte ptr [bp+MbrPartitionIndicator] ; AX = MbrPartitionIndex
cmp al, 0ffh ; 0xFF means do legacy MBR boot
jnz EfiDbr
LegacyMbr:
mov eax, 00000600h ; Assume LegacyMBR is backuped in Sector 6
jmp StartReadTo7C00 ; EAX = Header/Sector/Tracker/Zero
EfiDbr:
cmp al, 4 ; MbrPartitionIndex should < 4
jae BadDbr
shl ax, 4 ; AX = MBREntrySize * Index
add ax, 1beh ; AX = MBREntryOffset
mov di, ax ; 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
mov eax, dword ptr es:[bp + di + 8] ; Start LBA
mov edx, eax
shr edx, 16 ; DX:AX = Start LBA
; = Ci * (H * S) + Hi * S + (Si - 1)
; Calculate C/H/S according to LBA
mov bp, 7bfah
div word ptr [bp+2] ; AX = Hi + H*Ci
; DX = Si - 1
inc dx ; DX = Si
push dx ; 0000:7bfa = Si <----
xor dx, dx ; DX:AX = Hi + H*Ci
div word ptr [bp+4] ; AX = Ci <----
; DX = Hi <----
StartReadTo7C00:
mov cl, byte ptr [bp] ; Si
mov ch, al ; Ci[0-7]
or cl, ah ; Ci[8,9]
mov bx, 7c00h ; ES:BX = 0000:7C00h
mov ah, 2h ; Function 02h
mov al, 1 ; 1 Sector
mov dh, dl ; Hi
mov bp, 0600h
mov dl, byte ptr [bp + PhysicalDrive] ; Drive number
int 13h
jc BadDbr
; ****************************************************************************
; Transfer control to BootSector - Jump to 0x0000:0x7C00
; ****************************************************************************
xor ax, ax
push ax ; PUSH 0x0000 - Segment
mov di, 07c00h
push di ; PUSH 0x7C00 - Offset
retf ; JMP 0x0000:0x7C00
; ****************************************************************************
; ERROR Condition:
; ****************************************************************************
BadDbr:
push ax
mov ax, 0b800h
mov es, ax
mov ax, 060h
mov ds, ax
lea si, cs:[ErrorString]
mov di, 320
pop ax
call A2C
mov [si+16], ah
mov [si+18], al
mov cx, 10
rep movsw
Halt:
jmp Halt
StartString:
db 'M', 0ch, 'B', 0ch, 'R', 0ch, ' ', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
ErrorString:
db 'M', 0ch, 'B', 0ch, 'R', 0ch, ' ', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, ':', 0ch, '?', 0ch, '?', 0ch
; ****************************************************************************
; A2C - convert Ascii code stored in AH to character stored in AX
; ****************************************************************************
A2C:
mov al, ah
shr ah, 4
and al, 0Fh
add ah, '0'
add al, '0'
cmp ah, '9'
jle @f
add ah, 7
@@:
cmp al, '9'
jle @f
add al, 7
@@:
ret
; ****************************************************************************
; PhysicalDrive - Used to indicate which disk to be boot
; Can be patched by tool
; ****************************************************************************
org 01B6h
PhysicalDrive db 80h
; ****************************************************************************
; 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 01B7h
MbrPartitionIndicator db 0
; ****************************************************************************
; Unique MBR signature
; ****************************************************************************
org 01B8h
db 'DUET'
; ****************************************************************************
; Unknown
; ****************************************************************************
org 01BCh
dw 0
; ****************************************************************************
; MBR Entry - To be patched
; ****************************************************************************
org 01BEh
dd 0, 0, 0, 0
org 01CEh
dd 0, 0, 0, 0
org 01DEh
dd 0, 0, 0, 0
org 01EEh
dd 0, 0, 0, 0
; ****************************************************************************
; Sector Signature
; ****************************************************************************
org 01FEh
SectorSignature:
dw 0aa55h ; Boot Sector Signature
end

View File

@ -0,0 +1,288 @@
;------------------------------------------------------------------------------
;*
;* 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
FAT_DIRECTORY_ENTRY_SIZE EQU 020h
FAT_DIRECTORY_ENTRY_SHIFT EQU 5
BLOCK_SIZE EQU 0200h
BLOCK_MASK EQU 01ffh
BLOCK_SHIFT EQU 9
; "EFILDR_____"
LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"
LOADER_FILENAME_PART2 EQU 020205244h ; "DR__"
LOADER_FILENAME_PART3 EQU 020202020h ; "____"
org 0h
Ia32Jump:
jmp BootSectorEntryPoint ; JMP inst - 3 bytes
nop
OemId db "INTEL " ; OemId - 8 bytes
; BPB data below will be fixed by tool
SectorSize dw 0 ; Sector Size - 16 bits
SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
ReservedSectors dw 0 ; Reserved Sectors - 16 bits
NoFats db 0 ; Number of FATs - 8 bits
RootEntries dw 0 ; Root Entries - 16 bits
Sectors dw 0 ; Number of Sectors - 16 bits
Media db 0 ; Media - 8 bits - ignored
SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
Heads dw 0 ; Heads - 16 bits - ignored
HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
LargeSectors dd 0 ; Large Sectors - 32 bits
PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
CurrentHead db 0 ; Current Head - 8 bits
Signature db 0 ; Signature - 8 bits - ignored
Id db " " ; Id - 4 bytes
FatLabel db " " ; Label - 11 bytes
SystemId db "FAT12 " ; SystemId - 8 bytes
BootSectorEntryPoint:
ASSUME ds:@code
ASSUME ss:@code
; ****************************************************************************
; Start Print
; ****************************************************************************
lea si, cs:[StartString]
call PrintString
; ****************************************************************************
; Print over
; ****************************************************************************
mov ax,cs ; ax = 0
mov ss,ax ; ss = 0
add ax,1000h
mov ds,ax
mov sp,07c00h ; sp = 0x7c00
mov bp,sp ; bp = 0x7c00
mov ah,8 ; ah = 8 - Get Drive Parameters Function
mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
int 13h ; Get Drive Parameters
xor ax,ax ; ax = 0
mov al,dh ; al = dh
inc al ; MaxHead = al + 1
push ax ; 0000:7bfe = MaxHead
mov al,cl ; al = cl
and al,03fh ; MaxSector = al & 0x3f
push ax ; 0000:7bfc = MaxSector
cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
jne BadBootSector
mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
mov bx,cx ; bx = size of the Root Directory in bytes
and bx,BLOCK_MASK ; See if it is an even number of sectors long
jne BadBootSector ; If is isn't, then the boot sector is bad.
mov bx,cx ; bx = size of the Root Directory in bytes
shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
mov al,byte ptr [bp+NoFats] ; al = NoFats
xor ah,ah ; ah = 0 ==> ax = NoFats
mul word ptr [bp+SectorsPerFat] ; ax = NoFats * SectorsPerFat
add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
push ds
pop es
xor di,di ; Store directory in es:di = 1000:0000
call ReadBlocks ; Read entire Root Directory
add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
mov word ptr [bp],ax ; Save FirstClusterLBA (FirstDataSector) for later use
; dx - variable storage (initial value is 0)
; bx - loader (initial value is 0)
xor dx, dx
xor bx, bx
FindEFILDR:
cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
jne FindVARSTORE
cmp dword ptr [di+4],LOADER_FILENAME_PART2
jne FindVARSTORE
cmp dword ptr [di+7],LOADER_FILENAME_PART3
jne FindVARSTORE
mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
test 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"
cmp dword ptr [di], 056494645h ; Compare to "EFIV"
jne FindNext
cmp dword ptr [di+4], 020205241h ; Compare to "AR "
jne FindNext
cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
jne FindNext
mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
add dx, 26
test bx, bx
je FindNext ; Efildr is not loaded
jmp FoundAll
FindNext:
; go to next find
add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
; TODO: jump to FindVarStore if ...
jne FindEFILDR
jmp NotFoundAll
FoundAll:
FoundEFILDR:
mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
mov ax,cs ; Destination = 2000:0000
add ax,2000h
mov es,ax
xor di,di
ReadFirstClusterOfEFILDR:
mov ax,cx ; ax = StartCluster
sub ax,2 ; ax = StartCluster - 2
xor bh,bh
mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
push dx
mul bx
pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
xor bh,bh
mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
push es
call ReadBlocks
pop ax
JumpIntoFirstSectorOfEFILDR:
mov word ptr [bp+JumpSegment],ax
JumpFarInstruction:
db 0eah
JumpOffset:
dw 0000h
JumpSegment:
dw 2000h
PrintString:
mov ax,0b800h
mov es,ax
mov ax, 07c0h
mov ds, ax
mov cx, 7
mov di, 160
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
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 edx,edx ; edx = 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 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
; ****************************************************************************
; ERROR Condition:
; ****************************************************************************
NotFoundAll:
; if we found EFILDR, continue
test bx,bx
jne FoundEFILDR
BadBootSector:
DiskError:
lea si, cs:[ErrorString]
call PrintString
Halt:
jmp Halt
StartString:
db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
ErrorString:
db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
; ****************************************************************************
; LBA Offset for BootSector, need patched by tool for HD boot.
; ****************************************************************************
org 01fah
LBAOffsetForBootSector:
dd 0h
; ****************************************************************************
; Sector Signature
; ****************************************************************************
org 01feh
SectorSignature:
dw 0aa55h ; Boot Sector Signature
end

288
DuetPkg/BootSector/bs16.asm Normal file
View File

@ -0,0 +1,288 @@
;------------------------------------------------------------------------------
;*
;* 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
FAT_DIRECTORY_ENTRY_SIZE EQU 020h
FAT_DIRECTORY_ENTRY_SHIFT EQU 5
BLOCK_SIZE EQU 0200h
BLOCK_MASK EQU 01ffh
BLOCK_SHIFT EQU 9
; "EFILDR_____"
LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"
LOADER_FILENAME_PART2 EQU 036315244h ; "DR16"
LOADER_FILENAME_PART3 EQU 020202036h ; "6___"
org 0h
Ia32Jump:
jmp BootSectorEntryPoint ; JMP inst - 3 bytes
nop
OemId db "INTEL " ; OemId - 8 bytes
; BPB data below will be fixed by tool
SectorSize dw 0 ; Sector Size - 16 bits
SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
ReservedSectors dw 0 ; Reserved Sectors - 16 bits
NoFats db 0 ; Number of FATs - 8 bits
RootEntries dw 0 ; Root Entries - 16 bits
Sectors dw 0 ; Number of Sectors - 16 bits
Media db 0 ; Media - 8 bits - ignored
SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
Heads dw 0 ; Heads - 16 bits - ignored
HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
LargeSectors dd 0 ; Large Sectors - 32 bits
PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
CurrentHead db 0 ; Current Head - 8 bits
Signature db 0 ; Signature - 8 bits - ignored
Id db " " ; Id - 4 bytes
FatLabel db " " ; Label - 11 bytes
SystemId db "FAT16 " ; SystemId - 8 bytes
BootSectorEntryPoint:
ASSUME ds:@code
ASSUME ss:@code
; ****************************************************************************
; Start Print
; ****************************************************************************
lea si, cs:[StartString]
call PrintString
; ****************************************************************************
; Print over
; ****************************************************************************
mov ax,cs ; ax = 0
mov ss,ax ; ss = 0
add ax,1000h
mov ds,ax
mov sp,07c00h ; sp = 0x7c00
mov bp,sp ; bp = 0x7c00
mov ah,8 ; ah = 8 - Get Drive Parameters Function
mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
int 13h ; Get Drive Parameters
xor ax,ax ; ax = 0
mov al,dh ; al = dh
inc al ; MaxHead = al + 1
push ax ; 0000:7bfe = MaxHead
mov al,cl ; al = cl
and al,03fh ; MaxSector = al & 0x3f
push ax ; 0000:7bfc = MaxSector
cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
jne BadBootSector
mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
mov bx,cx ; bx = size of the Root Directory in bytes
and bx,BLOCK_MASK ; See if it is an even number of sectors long
jne BadBootSector ; If is isn't, then the boot sector is bad.
mov bx,cx ; bx = size of the Root Directory in bytes
shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
mov al,byte ptr [bp+NoFats] ; al = NoFats
xor ah,ah ; ah = 0 ==> ax = NoFats
mul word ptr [bp+SectorsPerFat] ; ax = NoFats * SectorsPerFat
add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
push ds
pop es
xor di,di ; Store directory in es:di = 1000:0000
call ReadBlocks ; Read entire Root Directory
add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
mov word ptr [bp],ax ; Save FirstClusterLBA (FirstDataSector) for later use
; dx - variable storage (initial value is 0)
; bx - loader (initial value is 0)
xor dx, dx
xor bx, bx
FindEFILDR:
cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
jne FindVARSTORE
cmp dword ptr [di+4],LOADER_FILENAME_PART2
jne FindVARSTORE
cmp dword ptr [di+7],LOADER_FILENAME_PART3
jne FindVARSTORE
mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
test 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"
cmp dword ptr [di], 056494645h ; Compare to "EFIV"
jne FindNext
cmp dword ptr [di+4], 020205241h ; Compare to "AR "
jne FindNext
cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
jne FindNext
mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
add dx, 26
test bx, bx
je FindNext ; Efildr is not loaded
jmp FoundAll
FindNext:
; go to next find
add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
; TODO: jump to FindVarStore if ...
jne FindEFILDR
jmp NotFoundAll
FoundAll:
FoundEFILDR:
mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
mov ax,cs ; Destination = 2000:0000
add ax,2000h
mov es,ax
xor di,di
ReadFirstClusterOfEFILDR:
mov ax,cx ; ax = StartCluster
sub ax,2 ; ax = StartCluster - 2
xor bh,bh
mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
push dx
mul bx
pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
xor bh,bh
mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
push es
call ReadBlocks
pop ax
JumpIntoFirstSectorOfEFILDR:
mov word ptr [bp+JumpSegment],ax
JumpFarInstruction:
db 0eah
JumpOffset:
dw 0000h
JumpSegment:
dw 2000h
PrintString:
mov ax,0b800h
mov es,ax
mov ax, 07c0h
mov ds, ax
mov cx, 7
mov di, 160
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
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 edx,edx ; edx = 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 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
; ****************************************************************************
; ERROR Condition:
; ****************************************************************************
NotFoundAll:
; if we found EFILDR, continue
test bx,bx
jne FoundEFILDR
BadBootSector:
DiskError:
lea si, cs:[ErrorString]
call PrintString
Halt:
jmp Halt
StartString:
db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
ErrorString:
db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
; ****************************************************************************
; LBA Offset for BootSector, need patched by tool for HD boot.
; ****************************************************************************
org 01fah
LBAOffsetForBootSector:
dd 0h
; ****************************************************************************
; Sector Signature
; ****************************************************************************
org 01feh
SectorSignature:
dw 0aa55h ; Boot Sector Signature
end

310
DuetPkg/BootSector/bs32.asm Normal file
View File

@ -0,0 +1,310 @@
;------------------------------------------------------------------------------
;*
;* 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.
;*
;* bs32.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
; "EFILDR_____"
LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"
LOADER_FILENAME_PART2 EQU 030325244h ; "DR20"
LOADER_FILENAME_PART3 EQU 020202030h ; "0___"
org 0h
Ia32Jump:
jmp BootSectorEntryPoint ; JMP inst - 3 bytes
nop
OemId db "INTEL " ; OemId - 8 bytes
; BPB data below will be fixed by tool
SectorSize dw 0 ; Sector Size - 16 bits
SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
ReservedSectors dw 0 ; Reserved Sectors - 16 bits
NoFats db 0 ; Number of FATs - 8 bits
RootEntries dw 0 ; Root Entries - 16 bits
Sectors dw 0 ; Number of Sectors - 16 bits
Media db 0 ; Media - 8 bits - ignored
SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
Heads dw 0 ; Heads - 16 bits - ignored
HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
LargeSectors dd 0 ; Large Sectors - 32 bits
;******************************************************************************
;
;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 0 ; Sectors Per FAT for FAT32 - 4 bytes
ExtFlags dw 0 ; Mirror Flag - 2 bytes
FSVersion dw 0 ; File System Version - 2 bytes
RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes
FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes
BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes
Reserved db 12 dup(0) ; Reserved Field - 12 bytes
PhysicalDrive db 0 ; Physical Drive Number - 1 byte
Reserved1 db 0 ; Reserved Field - 1 byte
Signature db 0 ; Extended Boot Signature - 1 byte
VolId db " " ; Volume Serial Number - 4 bytes
FatLabel db " " ; Volume Label - 11 bytes
FileSystemType db "FAT32 " ; File System Type - 8 bytes
BootSectorEntryPoint:
ASSUME ds:@code
ASSUME ss:@code
; ****************************************************************************
; Start Print
; ****************************************************************************
lea si, cs:[StartString]
call PrintString
; ****************************************************************************
; Print over
; ****************************************************************************
mov ax,cs ; ax = 0
mov ss,ax ; ss = 0
add ax,1000h
mov ds,ax
mov sp,07c00h ; sp = 0x7c00
mov bp,sp ; bp = 0x7c00
mov ah,8 ; ah = 8 - Get Drive Parameters Function
mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
int 13h ; Get Drive Parameters
xor ax,ax ; ax = 0
mov al,dh ; al = dh
inc al ; MaxHead = al + 1
push ax ; 0000:7bfe = MaxHead
mov al,cl ; al = cl
and al,03fh ; MaxSector = al & 0x3f
push ax ; 0000:7bfc = MaxSector
cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
jne BadBootSector
mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
mov bx,cx ; bx = size of the Root Directory in bytes
and bx,BLOCK_MASK ; See if it is an even number of sectors long
jne BadBootSector ; If is isn't, then the boot sector is bad.
mov bx,cx ; bx = size of the Root Directory in bytes
shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
mov al,byte ptr [bp+NoFats] ; al = NoFats
xor ah,ah ; ah = 0 ==> ax = NoFats
mul word ptr [bp+SectorsPerFat32] ; ax = NoFats * SectorsPerFat
add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA
mov word ptr [bp],ax ; Save FirstClusterLBA for later use
mov ax,word ptr [bp+RootCluster] ; ax = StartCluster of Root Directory
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 ds
pop es
xor di,di ; Store directory in es:di = 1000:0000
call ReadBlocks ; Read StartCluster of Root Directory
; dx - variable storage (initial value is 0)
; bx - loader (initial value is 0)
xor dx, dx
xor bx, bx
FindEFILDR:
cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
jne FindVARSTORE
cmp dword ptr [di+4],LOADER_FILENAME_PART2
jne FindVARSTORE
cmp dword ptr [di+7],LOADER_FILENAME_PART3
jne FindVARSTORE
mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
test 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"
cmp dword ptr [di], 056494645h ; Compare to "EFIV"
jne FindNext
cmp dword ptr [di+4], 020205241h ; Compare to "AR "
jne FindNext
cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
jne FindNext
mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
add dx, 26
test bx, bx
je FindNext ; Efildr is not loaded
jmp FoundAll
FindNext:
; go to next find
add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
; TODO: jump to FindVarStore if ...
jne FindEFILDR
jmp NotFoundAll
FoundAll:
FoundEFILDR:
mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
mov ax,cs ; Destination = 2000:0000
add ax,2000h
mov es,ax
xor di,di
ReadFirstClusterOfEFILDR:
mov ax,cx ; ax = StartCluster
sub ax,2 ; ax = StartCluster - 2
xor bh,bh
mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
push dx
mul bx
pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
xor bh,bh
mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
push es
call ReadBlocks
pop ax
JumpIntoFirstSectorOfEFILDR:
mov word ptr [bp+JumpSegment],ax
JumpFarInstruction:
db 0eah
JumpOffset:
dw 0000h
JumpSegment:
dw 2000h
PrintString:
mov ax,0b800h
mov es,ax
mov ax, 07c0h
mov ds, ax
mov cx, 7
mov di, 160
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
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 edx,edx ; edx = 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 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
; ****************************************************************************
; ERROR Condition:
; ****************************************************************************
NotFoundAll:
; if we found EFILDR, continue
test bx,bx
jne FoundEFILDR
BadBootSector:
DiskError:
lea si, cs:[ErrorString]
call PrintString
Halt:
jmp Halt
StartString:
db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
ErrorString:
db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
; ****************************************************************************
; LBA Offset for BootSector, need patched by tool for HD boot.
; ****************************************************************************
org 01fah
LBAOffsetForBootSector:
dd 0h
; ****************************************************************************
; Sector Signature
; ****************************************************************************
org 01feh
SectorSignature:
dw 0aa55h ; Boot Sector Signature
end

View File

@ -0,0 +1,581 @@
;------------------------------------------------------------------------------
;*
;* 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.
;*
;* efi32.asm
;*
;* Abstract:
;*
;------------------------------------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Now in 32-bit protected mode.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.486
.model flat
.stack
.code
org 21000h
DEFAULT_HANDLER_SIZE EQU INT1 - INT0
JmpCommonIdtEntry macro
; jmp commonIdtEntry - this must be hand coded to keep the assembler from
; using a 8 bit reletive jump when the entries are
; within 255 bytes of the common entry. This must
; be done to maintain the consistency of the size
; of entry points...
db 0e9h ; jmp 16 bit relative
dd commonIdtEntry - $ - 4 ; offset to jump to
endm
Start:
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov esp,0001ffff0h
call ClearScreen
; Populate IDT with meaningful offsets for exception handlers...
sidt fword ptr [Idtr] ; get fword address of IDT
mov eax, offset Halt
mov ebx, eax ; use bx to copy 15..0 to descriptors
shr eax, 16 ; use ax to copy 31..16 to descriptors
mov ecx, 78h ; 78h IDT entries to initialize with unique entry points (exceptions)
mov esi, [offset Idtr + 2]
mov edi, [esi]
@@: ; loop through all IDT entries exception handlers and initialize to default handler
mov word ptr [edi], bx ; write bits 15..0 of offset
mov word ptr [edi+2], 20h ; SYS_CODE_SEL from GDT
mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
mov word ptr [edi+6], ax ; write bits 31..16 of offset
add edi, 8 ; move up to next descriptor
add bx, DEFAULT_HANDLER_SIZE ; move to next entry point
loop @b ; loop back through again until all descriptors are initialized
;; at this point edi contains the offset of the descriptor for INT 20
;; and bx contains the low 16 bits of the offset of the default handler
;; so initialize all the rest of the descriptors with these two values...
; mov ecx, 101 ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)
;@@: ; loop through all IDT entries exception handlers and initialize to default handler
; mov word ptr [edi], bx ; write bits 15..0 of offset
; mov word ptr [edi+2], 20h ; SYS_CODE_SEL from GDT
; mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
; mov word ptr [edi+6], ax ; write bits 31..16 of offset
; add edi, 8 ; move up to next descriptor
; loop @b ; loop back through again until all descriptors are initialized
;; DUMP location of IDT and several of the descriptors
; mov ecx, 8
; mov eax, [offset Idtr + 2]
; mov eax, [eax]
; mov edi, 0b8000h
; call PrintDword
; mov esi, eax
; mov edi, 0b80a0h
; jmp OuterLoop
;;
;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler...
; mov eax, 011111111h
; mov ebx, 022222222h
; mov ecx, 033333333h
; mov edx, 044444444h
; mov ebp, 055555555h
; mov esi, 066666666h
; mov edi, 077777777h
; push 011111111h
; push 022222222h
; push 033333333h
; int 119
mov esi,022000h ; esi = 22000
mov eax,[esi+014h] ; eax = [22014]
add esi,eax ; esi = 22000 + [22014] = Base of EFILDR.C
mov ebp,[esi+03ch] ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C
add ebp,esi
mov edi,[ebp+034h] ; edi = [[22000 + [22014] + 3c] + 30] = ImageBase
mov eax,[ebp+028h] ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint
add eax,edi ; eax = ImageBase + EntryPoint
mov dword ptr [EfiLdrOffset],eax ; Modify far jump instruction for correct entry point
mov bx,word ptr[ebp+6] ; bx = Number of sections
xor eax,eax
mov ax,word ptr[ebp+014h] ; ax = Optional Header Size
add ebp,eax
add ebp,018h ; ebp = Start of 1st Section
SectionLoop:
push esi ; Save Base of EFILDR.C
push edi ; Save ImageBase
add esi,[ebp+014h] ; esi = Base of EFILDR.C + PointerToRawData
add edi,[ebp+00ch] ; edi = ImageBase + VirtualAddress
mov ecx,[ebp+010h] ; ecs = SizeOfRawData
cld
shr ecx,2
rep movsd
pop edi ; Restore ImageBase
pop esi ; Restore Base of EFILDR.C
add bp,028h ; ebp = ebp + 028h = Pointer to next section record
dec bx
cmp bx,0
jne SectionLoop
movzx eax, word ptr [Idtr] ; get size of IDT
inc eax
add eax, dword ptr [Idtr + 2] ; add to base of IDT to get location of memory map...
push eax ; push memory map location on stack for call to EFILDR...
push eax ; push return address (useless, just for stack balance)
db 0b8h
EfiLdrOffset:
dd 000401000h ; Offset of EFILDR
; mov eax, 401000h
push eax
ret
; db "**** DEFAULT IDT ENTRY ***",0
align 02h
Halt:
INT0:
push 0h ; push error code place holder on the stack
push 0h
JmpCommonIdtEntry
; db 0e9h ; jmp 16 bit reletive
; dd commonIdtEntry - $ - 4 ; offset to jump to
INT1:
push 0h ; push error code place holder on the stack
push 1h
JmpCommonIdtEntry
INT2:
push 0h ; push error code place holder on the stack
push 2h
JmpCommonIdtEntry
INT3:
push 0h ; push error code place holder on the stack
push 3h
JmpCommonIdtEntry
INT4:
push 0h ; push error code place holder on the stack
push 4h
JmpCommonIdtEntry
INT5:
push 0h ; push error code place holder on the stack
push 5h
JmpCommonIdtEntry
INT6:
push 0h ; push error code place holder on the stack
push 6h
JmpCommonIdtEntry
INT7:
push 0h ; push error code place holder on the stack
push 7h
JmpCommonIdtEntry
INT8:
; Double fault causes an error code to be pushed so no phony push necessary
nop
nop
push 8h
JmpCommonIdtEntry
INT9:
push 0h ; push error code place holder on the stack
push 9h
JmpCommonIdtEntry
INT10:
; Invalid TSS causes an error code to be pushed so no phony push necessary
nop
nop
push 10
JmpCommonIdtEntry
INT11:
; Segment Not Present causes an error code to be pushed so no phony push necessary
nop
nop
push 11
JmpCommonIdtEntry
INT12:
; Stack fault causes an error code to be pushed so no phony push necessary
nop
nop
push 12
JmpCommonIdtEntry
INT13:
; GP fault causes an error code to be pushed so no phony push necessary
nop
nop
push 13
JmpCommonIdtEntry
INT14:
; Page fault causes an error code to be pushed so no phony push necessary
nop
nop
push 14
JmpCommonIdtEntry
INT15:
push 0h ; push error code place holder on the stack
push 15
JmpCommonIdtEntry
INT16:
push 0h ; push error code place holder on the stack
push 16
JmpCommonIdtEntry
INT17:
; Alignment check causes an error code to be pushed so no phony push necessary
nop
nop
push 17
JmpCommonIdtEntry
INT18:
push 0h ; push error code place holder on the stack
push 18
JmpCommonIdtEntry
INT19:
push 0h ; push error code place holder on the stack
push 19
JmpCommonIdtEntry
INTUnknown:
REPEAT (78h - 20)
push 0h ; push error code place holder on the stack
; push xxh ; push vector number
db 06ah
db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
JmpCommonIdtEntry
ENDM
commonIdtEntry:
pushad
mov ebp, esp
;;
;; At this point the stack looks like this:
;;
;; eflags
;; Calling CS
;; Calling EIP
;; Error code or 0
;; Int num or 0ffh for unknown int num
;; eax
;; ecx
;; edx
;; ebx
;; esp
;; ebp
;; esi
;; edi <------- ESP, EBP
;;
call ClearScreen
mov esi, offset String1
call PrintString
mov eax, [ebp + 32] ;; move Int number into EAX
cmp eax, 19
ja PrintDefaultString
PrintExceptionString:
shl eax, 2 ;; multiply by 4 to get offset from StringTable to actual string address
add eax, offset StringTable
mov esi, [eax]
jmp PrintTheString
PrintDefaultString:
mov esi, offset IntUnknownString
; patch Int number
mov edx, eax
call A2C
mov [esi + 1], al
mov eax, edx
shr eax, 4
call A2C
mov [esi], al
PrintTheString:
call PrintString
mov esi, offset String2
call PrintString
mov eax, [ebp+44] ; CS
call PrintDword
mov al, ':'
mov byte ptr [edi], al
add edi, 2
mov eax, [ebp+40] ; EIP
call PrintDword
mov esi, offset String3
call PrintString
mov edi, 0b8140h
mov esi, offset StringEax ; eax
call PrintString
mov eax, [ebp+28]
call PrintDword
mov esi, offset StringEbx ; ebx
call PrintString
mov eax, [ebp+16]
call PrintDword
mov esi, offset StringEcx ; ecx
call PrintString
mov eax, [ebp+24]
call PrintDword
mov esi, offset StringEdx ; edx
call PrintString
mov eax, [ebp+20]
call PrintDword
mov esi, offset StringEcode ; error code
call PrintString
mov eax, [ebp+36]
call PrintDword
mov edi, 0b81e0h
mov esi, offset StringEsp ; esp
call PrintString
mov eax, [ebp+12]
call PrintDword
mov esi, offset StringEbp ; ebp
call PrintString
mov eax, [ebp+8]
call PrintDword
mov esi, offset StringEsi ; esi
call PrintString
mov eax, [ebp+4]
call PrintDword
mov esi, offset StringEdi ; edi
call PrintString
mov eax, [ebp]
call PrintDword
mov esi, offset StringEflags ; eflags
call PrintString
mov eax, [ebp+48]
call PrintDword
mov edi, 0b8320h
mov esi, ebp
add esi, 52
mov ecx, 8
OuterLoop:
push ecx
mov ecx, 8
mov edx, edi
InnerLoop:
mov eax, [esi]
call PrintDword
add esi, 4
mov al, ' '
mov [edi], al
add edi, 2
loop InnerLoop
pop ecx
add edx, 0a0h
mov edi, edx
loop OuterLoop
mov edi, 0b8960h
mov eax, [ebp+40] ; EIP
sub eax, 32 * 4
mov esi, eax ; esi = eip - 32 DWORD linear (total 64 DWORD)
mov ecx, 8
OuterLoop1:
push ecx
mov ecx, 8
mov edx, edi
InnerLoop1:
mov eax, [esi]
call PrintDword
add esi, 4
mov al, ' '
mov [edi], al
add edi, 2
loop InnerLoop1
pop ecx
add edx, 0a0h
mov edi, edx
loop OuterLoop1
; wbinvd ; Ken: this intruction does not support in early than 486 arch
@@:
jmp @b
;
; return
;
mov esp, ebp
popad
add esp, 8 ; error code and INT number
iretd
PrintString:
push eax
@@:
mov al, byte ptr [esi]
cmp al, 0
je @f
mov byte ptr [edi], al
inc esi
add edi, 2
jmp @b
@@:
pop eax
ret
;; EAX contains dword to print
;; EDI contains memory location (screen location) to print it to
PrintDword:
push ecx
push ebx
push eax
mov ecx, 8
looptop:
rol eax, 4
mov bl, al
and bl, 0fh
add bl, '0'
cmp bl, '9'
jle @f
add bl, 7
@@:
mov byte ptr [edi], bl
add edi, 2
loop looptop
wbinvd
pop eax
pop ebx
pop ecx
ret
ClearScreen:
push eax
push ecx
mov al, ' '
mov ah, 0ch
mov edi, 0b8000h
mov ecx, 80 * 24
@@:
mov word ptr [edi], ax
add edi, 2
loop @b
mov edi, 0b8000h
pop ecx
pop eax
ret
A2C:
and al, 0fh
add al, '0'
cmp al, '9'
jle @f
add al, 7
@@:
ret
String1 db "*** INT ",0
Int0String db "00h Divide by 0 -",0
Int1String db "01h Debug exception -",0
Int2String db "02h NMI -",0
Int3String db "03h Breakpoint -",0
Int4String db "04h Overflow -",0
Int5String db "05h Bound -",0
Int6String db "06h Invalid opcode -",0
Int7String db "07h Device not available -",0
Int8String db "08h Double fault -",0
Int9String db "09h Coprocessor seg overrun (reserved) -",0
Int10String db "0Ah Invalid TSS -",0
Int11String db "0Bh Segment not present -",0
Int12String db "0Ch Stack fault -",0
Int13String db "0Dh General protection fault -",0
Int14String db "0Eh Page fault -",0
Int15String db "0Fh (Intel reserved) -",0
Int16String db "10h Floating point error -",0
Int17String db "11h Alignment check -",0
Int18String db "12h Machine check -",0
Int19String db "13h SIMD Floating-Point Exception -",0
IntUnknownString db "??h Unknown interrupt -",0
StringTable dd offset Int0String, offset Int1String, offset Int2String, offset Int3String,
offset Int4String, offset Int5String, offset Int6String, offset Int7String,
offset Int8String, offset Int9String, offset Int10String, offset Int11String,
offset Int12String, offset Int13String, offset Int14String, offset Int15String,
offset Int16String, offset Int17String, offset Int18String, offset Int19String
String2 db " HALT!! *** (",0
String3 db ")",0
StringEax db "EAX=",0
StringEbx db " EBX=",0
StringEcx db " ECX=",0
StringEdx db " EDX=",0
StringEcode db " ECODE=",0
StringEsp db "ESP=",0
StringEbp db " EBP=",0
StringEsi db " ESI=",0
StringEdi db " EDI=",0
StringEflags db " EFLAGS=",0
Idtr df 0
org 21ffeh
BlockSignature:
dw 0aa55h
end

View File

@ -0,0 +1,787 @@
;------------------------------------------------------------------------------
;*
;* 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.
;*
;* efi64.asm
;*
;* Abstract:
;*
;------------------------------------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Now in 64-bit long mode.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.486
.model flat
.stack
.code
org 21000h
DEFAULT_HANDLER_SIZE EQU INT1 - INT0
JmpCommonIdtEntry macro
; jmp commonIdtEntry - this must be hand coded to keep the assembler from
; using a 8 bit reletive jump when the entries are
; within 255 bytes of the common entry. This must
; be done to maintain the consistency of the size
; of entry points...
db 0e9h ; jmp 16 bit reletive
dd commonIdtEntry - $ - 4 ; offset to jump to
endm
Start:
mov esp,0001fffe8h ; make final stack aligned
; set OSFXSR and OSXMMEXCPT because some code will use XMM register
db 0fh
db 20h
db 0e0h
; mov rax, cr4
bts eax, 9
bts eax, 0ah
db 0fh
db 22h
db 0e0h
; mov cr4, rax
call ClearScreen
; Populate IDT with meaningful offsets for exception handlers...
mov eax, offset Idtr
sidt fword ptr [eax] ; get fword address of IDT
mov eax, offset Halt
mov ebx, eax ; use bx to copy 15..0 to descriptors
shr eax, 16 ; use ax to copy 31..16 to descriptors
; 63..32 of descriptors is 0
mov ecx, 78h ; 78h IDT entries to initialize with unique entry points (exceptions)
mov esi, [offset Idtr + 2]
mov edi, [esi]
@@: ; loop through all IDT entries exception handlers and initialize to default handler
mov word ptr [edi], bx ; write bits 15..0 of offset
mov word ptr [edi+2], 38h ; SYS_CODE64_SEL from GDT
mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
mov word ptr [edi+6], ax ; write bits 31..16 of offset
mov dword ptr [edi+8], 0 ; write bits 63..32 of offset
add edi, 16 ; move up to next descriptor
add bx, DEFAULT_HANDLER_SIZE ; move to next entry point
loop @b ; loop back through again until all descriptors are initialized
;; at this point edi contains the offset of the descriptor for INT 20
;; and bx contains the low 16 bits of the offset of the default handler
;; so initialize all the rest of the descriptors with these two values...
; mov ecx, 101 ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)
;@@: ; loop through all IDT entries exception handlers and initialize to default handler
; mov word ptr [edi], bx ; write bits 15..0 of offset
; mov word ptr [edi+2], 38h ; SYS_CODE64_SEL from GDT
; mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
; mov word ptr [edi+6], ax ; write bits 31..16 of offset
; mov dword ptr [edi+8], 0 ; write bits 63..32 of offset
; add edi, 16 ; move up to next descriptor
; loop @b ; loop back through again until all descriptors are initialized
;; DUMP location of IDT and several of the descriptors
; mov ecx, 8
; mov eax, [offset Idtr + 2]
; mov eax, [eax]
; mov edi, 0b8000h
; call PrintQword
; mov esi, eax
; mov edi, 0b80a0h
; jmp OuterLoop
;;
;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler...
; mov eax, 011111111h
; mov ebx, 022222222h
; mov ecx, 033333333h
; mov edx, 044444444h
; mov ebp, 055555555h
; mov esi, 066666666h
; mov edi, 077777777h
; push 011111111h
; push 022222222h
; push 033333333h
; int 119
mov esi,022000h ; esi = 22000
mov eax,[esi+014h] ; eax = [22014]
add esi,eax ; esi = 22000 + [22014] = Base of EFILDR.C
mov ebp,[esi+03ch] ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C
add ebp,esi
mov edi,[ebp+030h] ; edi = [[22000 + [22014] + 3c] + 2c] = ImageBase (63..32 is zero, ignore)
mov eax,[ebp+028h] ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint
add eax,edi ; eax = ImageBase + EntryPoint
mov ebx, offset EfiLdrOffset
mov dword ptr [ebx],eax ; Modify far jump instruction for correct entry point
mov bx,word ptr[ebp+6] ; bx = Number of sections
xor eax,eax
mov ax,word ptr[ebp+014h] ; ax = Optional Header Size
add ebp,eax
add ebp,018h ; ebp = Start of 1st Section
SectionLoop:
push esi ; Save Base of EFILDR.C
push edi ; Save ImageBase
add esi,[ebp+014h] ; esi = Base of EFILDR.C + PointerToRawData
add edi,[ebp+00ch] ; edi = ImageBase + VirtualAddress
mov ecx,[ebp+010h] ; ecs = SizeOfRawData
cld
shr ecx,2
rep movsd
pop edi ; Restore ImageBase
pop esi ; Restore Base of EFILDR.C
add bp,028h ; ebp = ebp + 028h = Pointer to next section record
db 66h
db 0ffh
db 0cbh
; dec bx
cmp bx,0
jne SectionLoop
mov edx, offset Idtr
movzx eax, word ptr [edx] ; get size of IDT
db 0ffh
db 0c0h
; inc eax
add eax, dword ptr [edx + 2] ; add to base of IDT to get location of memory map...
xor ecx, ecx
mov ecx, eax ; put argument to RCX
db 48h
db 0c7h
db 0c0h
EfiLdrOffset:
dd 000401000h ; Offset of EFILDR
; mov rax, 401000h
db 50h
; push rax
; ret
db 0c3h
; db "**** DEFAULT IDT ENTRY ***",0
align 02h
Halt:
INT0:
push 0h ; push error code place holder on the stack
push 0h
JmpCommonIdtEntry
; db 0e9h ; jmp 16 bit reletive
; dd commonIdtEntry - $ - 4 ; offset to jump to
INT1:
push 0h ; push error code place holder on the stack
push 1h
JmpCommonIdtEntry
INT2:
push 0h ; push error code place holder on the stack
push 2h
JmpCommonIdtEntry
INT3:
push 0h ; push error code place holder on the stack
push 3h
JmpCommonIdtEntry
INT4:
push 0h ; push error code place holder on the stack
push 4h
JmpCommonIdtEntry
INT5:
push 0h ; push error code place holder on the stack
push 5h
JmpCommonIdtEntry
INT6:
push 0h ; push error code place holder on the stack
push 6h
JmpCommonIdtEntry
INT7:
push 0h ; push error code place holder on the stack
push 7h
JmpCommonIdtEntry
INT8:
; Double fault causes an error code to be pushed so no phony push necessary
nop
nop
push 8h
JmpCommonIdtEntry
INT9:
push 0h ; push error code place holder on the stack
push 9h
JmpCommonIdtEntry
INT10:
; Invalid TSS causes an error code to be pushed so no phony push necessary
nop
nop
push 10
JmpCommonIdtEntry
INT11:
; Segment Not Present causes an error code to be pushed so no phony push necessary
nop
nop
push 11
JmpCommonIdtEntry
INT12:
; Stack fault causes an error code to be pushed so no phony push necessary
nop
nop
push 12
JmpCommonIdtEntry
INT13:
; GP fault causes an error code to be pushed so no phony push necessary
nop
nop
push 13
JmpCommonIdtEntry
INT14:
; Page fault causes an error code to be pushed so no phony push necessary
nop
nop
push 14
JmpCommonIdtEntry
INT15:
push 0h ; push error code place holder on the stack
push 15
JmpCommonIdtEntry
INT16:
push 0h ; push error code place holder on the stack
push 16
JmpCommonIdtEntry
INT17:
; Alignment check causes an error code to be pushed so no phony push necessary
nop
nop
push 17
JmpCommonIdtEntry
INT18:
push 0h ; push error code place holder on the stack
push 18
JmpCommonIdtEntry
INT19:
push 0h ; push error code place holder on the stack
push 19
JmpCommonIdtEntry
INTUnknown:
REPEAT (78h - 20)
push 0h ; push error code place holder on the stack
; push xxh ; push vector number
db 06ah
db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
JmpCommonIdtEntry
ENDM
commonIdtEntry:
push eax
push ecx
push edx
push ebx
push esp
push ebp
push esi
push edi
db 41h
db 50h
; push r8
db 41h
db 51h
; push r9
db 41h
db 52h
; push r10
db 41h
db 53h
; push r11
db 41h
db 54h
; push r12
db 41h
db 55h
; push r13
db 41h
db 56h
; push r14
db 41h
db 57h
; push r15
db 48h
mov ebp, esp
; mov rbp, rsp
;;
;; At this point the stack looks like this:
;;
;; Calling SS
;; Calling RSP
;; rflags
;; Calling CS
;; Calling RIP
;; Error code or 0
;; Int num or 0ffh for unknown int num
;; rax
;; rcx
;; rdx
;; rbx
;; rsp
;; rbp
;; rsi
;; rdi
;; r8
;; r9
;; r10
;; r11
;; r12
;; r13
;; r14
;; r15 <------- RSP, RBP
;;
call ClearScreen
mov esi, offset String1
call PrintString
db 48h
mov eax, [ebp + 16*8] ;; move Int number into RAX
db 48h
cmp eax, 18
ja PrintDefaultString
PrintExceptionString:
shl eax, 3 ;; multiply by 8 to get offset from StringTable to actual string address
add eax, offset StringTable
mov esi, [eax]
jmp PrintTheString
PrintDefaultString:
mov esi, offset IntUnknownString
; patch Int number
mov edx, eax
call A2C
mov [esi + 1], al
mov eax, edx
shr eax, 4
call A2C
mov [esi], al
PrintTheString:
call PrintString
mov esi, offset String2
call PrintString
db 48h
mov eax, [ebp+19*8] ; CS
call PrintQword
mov al, ':'
mov byte ptr [edi], al
add edi, 2
db 48h
mov eax, [ebp+18*8] ; RIP
call PrintQword
mov esi, offset String3
call PrintString
mov edi, 0b8140h
mov esi, offset StringRax ; rax
call PrintString
db 48h
mov eax, [ebp+15*8]
call PrintQword
mov esi, offset StringRcx ; rcx
call PrintString
db 48h
mov eax, [ebp+14*8]
call PrintQword
mov esi, offset StringRdx ; rdx
call PrintString
db 48h
mov eax, [ebp+13*8]
call PrintQword
mov edi, 0b81e0h
mov esi, offset StringRbx ; rbx
call PrintString
db 48h
mov eax, [ebp+12*8]
call PrintQword
mov esi, offset StringRsp ; rsp
call PrintString
db 48h
mov eax, [ebp+21*8]
call PrintQword
mov esi, offset StringRbp ; rbp
call PrintString
db 48h
mov eax, [ebp+10*8]
call PrintQword
mov edi, 0b8280h
mov esi, offset StringRsi ; rsi
call PrintString
db 48h
mov eax, [ebp+9*8]
call PrintQword
mov esi, offset StringRdi ; rdi
call PrintString
db 48h
mov eax, [ebp+8*8]
call PrintQword
mov esi, offset StringEcode ; error code
call PrintString
db 48h
mov eax, [ebp+17*8]
call PrintQword
mov edi, 0b8320h
mov esi, offset StringR8 ; r8
call PrintString
db 48h
mov eax, [ebp+7*8]
call PrintQword
mov esi, offset StringR9 ; r9
call PrintString
db 48h
mov eax, [ebp+6*8]
call PrintQword
mov esi, offset StringR10 ; r10
call PrintString
db 48h
mov eax, [ebp+5*8]
call PrintQword
mov edi, 0b83c0h
mov esi, offset StringR11 ; r11
call PrintString
db 48h
mov eax, [ebp+4*8]
call PrintQword
mov esi, offset StringR12 ; r12
call PrintString
db 48h
mov eax, [ebp+3*8]
call PrintQword
mov esi, offset StringR13 ; r13
call PrintString
db 48h
mov eax, [ebp+2*8]
call PrintQword
mov edi, 0b8460h
mov esi, offset StringR14 ; r14
call PrintString
db 48h
mov eax, [ebp+1*8]
call PrintQword
mov esi, offset StringR15 ; r15
call PrintString
db 48h
mov eax, [ebp+0*8]
call PrintQword
mov esi, offset StringSs ; ss
call PrintString
db 48h
mov eax, [ebp+22*8]
call PrintQword
mov edi, 0b8500h
mov esi, offset StringRflags ; rflags
call PrintString
db 48h
mov eax, [ebp+20*8]
call PrintQword
mov edi, 0b8640h
mov esi, ebp
add esi, 23*8
mov ecx, 4
OuterLoop:
push ecx
mov ecx, 4
db 48h
mov edx, edi
InnerLoop:
db 48h
mov eax, [esi]
call PrintQword
add esi, 8
mov al, ' '
mov [edi], al
add edi, 2
loop InnerLoop
pop ecx
add edx, 0a0h
mov edi, edx
loop OuterLoop
mov edi, 0b8960h
db 48h
mov eax, [ebp+18*8] ; RIP
sub eax, 8 * 8
db 48h
mov esi, eax ; esi = rip - 8 QWORD linear (total 16 QWORD)
mov ecx, 4
OuterLoop1:
push ecx
mov ecx, 4
mov edx, edi
InnerLoop1:
db 48h
mov eax, [esi]
call PrintQword
add esi, 8
mov al, ' '
mov [edi], al
add edi, 2
loop InnerLoop1
pop ecx
add edx, 0a0h
mov edi, edx
loop OuterLoop1
wbinvd
@@:
jmp @b
;
; return
;
mov esp, ebp
; mov rsp, rbp
db 41h
db 5fh
; pop r15
db 41h
db 5eh
; pop r14
db 41h
db 5dh
; pop r13
db 41h
db 5ch
; pop r12
db 41h
db 5bh
; pop r11
db 41h
db 5ah
; pop r10
db 41h
db 59h
; pop r9
db 41h
db 58h
; pop r8
pop edi
pop esi
pop ebp
pop eax ; esp
pop ebx
pop edx
pop ecx
pop eax
db 48h
db 83h
db 0c4h
db 10h
; add esp, 16 ; error code and INT number
db 48h
db 0cfh
; iretq
PrintString:
push eax
@@:
mov al, byte ptr [esi]
cmp al, 0
je @f
mov byte ptr [edi], al
db 0ffh
db 0c6h
; inc esi
add edi, 2
jmp @b
@@:
pop eax
ret
;; RAX contains qword to print
;; RDI contains memory location (screen location) to print it to
PrintQword:
push ecx
push ebx
push eax
db 48h
db 0c7h
db 0c1h
dd 16
; mov rcx, 16
looptop:
db 48h
rol eax, 4
mov bl, al
and bl, 0fh
add bl, '0'
cmp bl, '9'
jle @f
add bl, 7
@@:
mov byte ptr [edi], bl
add edi, 2
loop looptop
wbinvd
pop eax
pop ebx
pop ecx
ret
ClearScreen:
push eax
push ecx
mov al, ' '
mov ah, 0ch
mov edi, 0b8000h
mov ecx, 80 * 24
@@:
mov word ptr [edi], ax
add edi, 2
loop @b
mov edi, 0b8000h
pop ecx
pop eax
ret
A2C:
and al, 0fh
add al, '0'
cmp al, '9'
jle @f
add al, 7
@@:
ret
String1 db "*** INT ",0
Int0String db "00h Divide by 0 -",0
Int1String db "01h Debug exception -",0
Int2String db "02h NMI -",0
Int3String db "03h Breakpoint -",0
Int4String db "04h Overflow -",0
Int5String db "05h Bound -",0
Int6String db "06h Invalid opcode -",0
Int7String db "07h Device not available -",0
Int8String db "08h Double fault -",0
Int9String db "09h Coprocessor seg overrun (reserved) -",0
Int10String db "0Ah Invalid TSS -",0
Int11String db "0Bh Segment not present -",0
Int12String db "0Ch Stack fault -",0
Int13String db "0Dh General protection fault -",0
Int14String db "0Eh Page fault -",0
Int15String db "0Fh (Intel reserved) -",0
Int16String db "10h Floating point error -",0
Int17String db "11h Alignment check -",0
Int18String db "12h Machine check -",0
Int19String db "13h SIMD Floating-Point Exception -",0
IntUnknownString db "??h Unknown interrupt -",0
StringTable dq offset Int0String, offset Int1String, offset Int2String, offset Int3String,
offset Int4String, offset Int5String, offset Int6String, offset Int7String,
offset Int8String, offset Int9String, offset Int10String, offset Int11String,
offset Int12String, offset Int13String, offset Int14String, offset Int15String,
offset Int16String, offset Int17String, offset Int18String, offset Int19String
String2 db " HALT!! *** (",0
String3 db ")",0
StringRax db "RAX=",0
StringRcx db " RCX=",0
StringRdx db " RDX=",0
StringRbx db "RBX=",0
StringRsp db " RSP=",0
StringRbp db " RBP=",0
StringRsi db "RSI=",0
StringRdi db " RDI=",0
StringEcode db " ECODE=",0
StringR8 db "R8 =",0
StringR9 db " R9 =",0
StringR10 db " R10=",0
StringR11 db "R11=",0
StringR12 db " R12=",0
StringR13 db " R13=",0
StringR14 db "R14=",0
StringR15 db " R15=",0
StringSs db " SS =",0
StringRflags db "RFLAGS=",0
Idtr df 0
df 0
org 21ffeh
BlockSignature:
dw 0aa55h
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,921 @@
;------------------------------------------------------------------------------
;*
;* 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.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
org 0h
Ia32Jump:
jmp BootSectorEntryPoint ; JMP inst - 3 bytes
nop
OemId db "INTEL " ; OemId - 8 bytes
SectorSize dw 0 ; Sector Size - 16 bits
SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
ReservedSectors dw 0 ; Reserved Sectors - 16 bits
NoFats db 0 ; Number of FATs - 8 bits
RootEntries dw 0 ; Root Entries - 16 bits
Sectors dw 0 ; Number of Sectors - 16 bits
Media db 0 ; Media - 8 bits - ignored
SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
Heads dw 0 ; Heads - 16 bits - ignored
HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
LargeSectors dd 0 ; Large Sectors - 32 bits
PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
CurrentHead db 0 ; Current Head - 8 bits
Signature db 0 ; Signature - 8 bits - ignored
VolId db " " ; Volume Serial Number- 4 bytes
FatLabel db " " ; Label - 11 bytes
SystemId db "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
mov bp,07c00h
push cx
; Read Efivar.bin
; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
mov ax,01900h
mov es,ax
test dx,dx
jnz CheckVarStoreSize
mov al,1
NoVarStore:
push es
; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
mov byte ptr es:[4],al
jmp SaveVolumeId
CheckVarStoreSize:
mov di,dx
cmp dword ptr ds:[di+2], 04000h
mov al,2
jne NoVarStore
LoadVarStore:
mov al,0
mov byte ptr es:[4],al
mov cx,word ptr[di]
; ES:DI = 1500:0
xor di,di
push es
mov ax,01500h
mov es,ax
call ReadFile
SaveVolumeId:
pop es
mov ax,word ptr [bp+VolId]
mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
mov ax,word ptr [bp+VolId+2]
mov word ptr es:[2],ax
; Read Efildr
pop cx
; cx = Start Cluster of Efildr -> BS.com has filled already
; ES:DI = 2000:0, first cluster will be read again
xor di,di ; di = 0
mov ax,02000h
mov es,ax
call ReadFile
mov ax,cs
mov word ptr cs:[JumpSegment],ax
JumpFarInstruction:
db 0eah
JumpOffset:
dw 0200h
JumpSegment:
dw 2000h
; ****************************************************************************
; 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
mov si,1 ; NumberOfClusters = 1
push cx ; Push Start Cluster onto stack
mov dx,0fffh ; CachedFatSectorNumber = 0xfff
FatChainLoop:
mov ax,cx ; ax = ClusterNumber
and ax,0ff8h ; ax = ax & 0xff8
cmp ax,0ff8h ; See if this is the last cluster
je FoundLastCluster ; Jump if last cluster found
mov ax,cx ; ax = ClusterNumber
shl ax,1 ; ax = ClusterNumber * 2
add ax,cx ; ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3
shr ax,1 ; FatOffset = ClusterNumber*3 / 2
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
and ax,1 ; See if this is an odd cluster number
je EvenFatEntry
shr bx,4 ; NextClusterNumber = NextClusterNumber >> 4
EvenFatEntry:
and bx,0fffh ; Strip upper 4 bits of NextClusterNumber
pop si ; Restore si
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:
pop 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
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 edx,edx ; edx = 0
movzx ebx,word ptr [bp] ; bx = MaxSector
div ebx ; ax = StartLBA / MaxSector
inc dx ; dx = (StartLBA % MaxSector) + 1
mov bx,word ptr [bp] ; bx = MaxSector
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:
push cs
pop ds
lea si, [ErrorString]
mov cx, 7
jmp PrintStringAndHalt
PrintStringAndHalt:
mov ax,0b800h
mov es,ax
mov di,160
rep movsw
Halt:
jmp Halt
ErrorString:
db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
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
jmp start
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
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
;
cli
; mov ax,0b800h
; mov es,ax
; mov byte ptr es:[164],'c'
; mov ax,cs
; mov es,ax
db 66h
lgdt fword ptr [gdtr]
db 66h
lidt fword ptr [idtr]
mov eax,cr0
or al,1
mov cr0,eax
mov eax,0008h ; Flat data descriptor
mov ebp,000400000h ; Destination of EFILDR32
mov ebx,000070000h ; Length of copy
JUMP:
; jmp far 0010:00020000
db 066h
db 0eah
dd 000020000h
dw 00010h
Empty8042InputBuffer:
mov cx,0
Empty8042Loop:
out DELAY_PORT,ax ; Delay 1us
in al,KBD_STATUS_PORT ; Read the 8042 Status Port
and al,02h ; Check the Input Buffer Full Flag
loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 02h
gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
dd 0 ; (GDT base gets set above)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; global descriptor table (GDT)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 02h
public GDT_BASE
GDT_BASE:
; null descriptor
NULL_SEL equ $-GDT_BASE
dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
; linear data segment descriptor
LINEAR_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; linear code segment descriptor
LINEAR_CODE_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; system data segment descriptor
SYS_DATA_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; system code segment descriptor
SYS_CODE_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE3_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE4_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE5_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
GDT_END:
align 02h
idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
dd 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 02h
public IDT_BASE
IDT_BASE:
; divide by zero (INT 0)
DIV_ZERO_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; debug exception (INT 1)
DEBUG_EXCEPT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; NMI (INT 2)
NMI_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; soft breakpoint (INT 3)
BREAKPOINT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; overflow (INT 4)
OVERFLOW_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; bounds check (INT 5)
BOUNDS_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; invalid opcode (INT 6)
INVALID_OPCODE_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; device not available (INT 7)
DEV_NOT_AVAIL_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; double fault (INT 8)
DOUBLE_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Coprocessor segment overrun - reserved (INT 9)
RSVD_INTR_SEL1 equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; invalid TSS (INT 0ah)
INVALID_TSS_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; segment not present (INT 0bh)
SEG_NOT_PRESENT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; stack fault (INT 0ch)
STACK_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; general protection (INT 0dh)
GP_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; page fault (INT 0eh)
PAGE_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Intel reserved - do not use (INT 0fh)
RSVD_INTR_SEL2 equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; floating point error (INT 10h)
FLT_POINT_ERR_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; alignment check (INT 11h)
ALIGNMENT_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; machine check (INT 12h)
MACHINE_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; SIMD floating-point exception (INT 13h)
SIMD_EXCEPTION_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
db (85 * 8) dup(0)
; IRQ 0 (System timer) - (INT 68h)
IRQ0_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 1 (8042 Keyboard controller) - (INT 69h)
IRQ1_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
IRQ2_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 3 (COM 2) - (INT 6bh)
IRQ3_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 4 (COM 1) - (INT 6ch)
IRQ4_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 5 (LPT 2) - (INT 6dh)
IRQ5_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 6 (Floppy controller) - (INT 6eh)
IRQ6_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 7 (LPT 1) - (INT 6fh)
IRQ7_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 8 (RTC Alarm) - (INT 70h)
IRQ8_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 9 - (INT 71h)
IRQ9_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 10 - (INT 72h)
IRQ10_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 11 - (INT 73h)
IRQ11_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 12 (PS/2 mouse) - (INT 74h)
IRQ12_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 13 (Floating point error) - (INT 75h)
IRQ13_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 14 (Secondary IDE) - (INT 76h)
IRQ14_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 15 (Primary IDE) - (INT 77h)
IRQ15_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
IDT_END:
align 02h
MemoryMapSize dd 0
MemoryMap dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 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
dd 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 0fe0h
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 0ffeh
BlockSignature:
dw 0aa55h
end

View File

@ -0,0 +1,914 @@
;------------------------------------------------------------------------------
;*
;* 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.
;*
;* start16.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
org 0h
Ia32Jump:
jmp BootSectorEntryPoint ; JMP inst - 3 bytes
nop
OemId db "INTEL " ; OemId - 8 bytes
SectorSize dw 0 ; Sector Size - 16 bits
SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
ReservedSectors dw 0 ; Reserved Sectors - 16 bits
NoFats db 0 ; Number of FATs - 8 bits
RootEntries dw 0 ; Root Entries - 16 bits
Sectors dw 0 ; Number of Sectors - 16 bits
Media db 0 ; Media - 8 bits - ignored
SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
Heads dw 0 ; Heads - 16 bits - ignored
HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
LargeSectors dd 0 ; Large Sectors - 32 bits
PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
CurrentHead db 0 ; Current Head - 8 bits
Signature db 0 ; Signature - 8 bits - ignored
VolId db " " ; Volume Serial Number- 4 bytes
FatLabel db " " ; Label - 11 bytes
SystemId db "FAT16 " ; 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
mov bp,07c00h
push cx
; Read Efivar.bin
; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
mov ax,01900h
mov es,ax
test dx,dx
jnz CheckVarStoreSize
mov al,1
NoVarStore:
push es
; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
mov byte ptr es:[4],al
jmp SaveVolumeId
CheckVarStoreSize:
mov di,dx
cmp dword ptr ds:[di+2], 04000h
mov al,2
jne NoVarStore
LoadVarStore:
mov al,0
mov byte ptr es:[4],al
mov cx,word ptr[di]
; ES:DI = 1500:0
xor di,di
push es
mov ax,01500h
mov es,ax
call ReadFile
SaveVolumeId:
pop es
mov ax,word ptr [bp+VolId]
mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
mov ax,word ptr [bp+VolId+2]
mov word ptr es:[2],ax
; Read Efildr
pop cx
; cx = Start Cluster of Efildr -> BS.com has filled already
; ES:DI = 2000:0, first cluster will be read again
xor di,di ; di = 0
mov ax,02000h
mov es,ax
call ReadFile
mov ax,cs
mov word ptr cs:[JumpSegment],ax
JumpFarInstruction:
db 0eah
JumpOffset:
dw 0200h
JumpSegment:
dw 2000h
; ****************************************************************************
; 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
mov si,1 ; NumberOfClusters = 1
push cx ; Push Start Cluster onto stack
mov dx,0fffh ; CachedFatSectorNumber = 0xfff
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,1 ; FatOffset = ClusterNumber * 2
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
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:
pop 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
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 edx,edx ; edx = 0
movzx ebx,word ptr [bp] ; bx = MaxSector
div ebx ; ax = StartLBA / MaxSector
inc dx ; dx = (StartLBA % MaxSector) + 1
mov bx,word ptr [bp] ; bx = MaxSector
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:
push cs
pop ds
lea si, [ErrorString]
mov cx, 7
jmp PrintStringAndHalt
PrintStringAndHalt:
mov ax,0b800h
mov es,ax
mov di,160
rep movsw
Halt:
jmp Halt
ErrorString:
db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
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
jmp start
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
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
;
cli
; mov ax,0b800h
; mov es,ax
; mov byte ptr es:[164],'c'
; mov ax,cs
; mov es,ax
db 66h
lgdt fword ptr [gdtr]
db 66h
lidt fword ptr [idtr]
mov eax,cr0
or al,1
mov cr0,eax
mov eax,0008h ; Flat data descriptor
mov ebp,000400000h ; Destination of EFILDR32
mov ebx,000070000h ; Length of copy
JUMP:
; jmp far 0010:00020000
db 066h
db 0eah
dd 000020000h
dw 00010h
Empty8042InputBuffer:
mov cx,0
Empty8042Loop:
out DELAY_PORT,ax ; Delay 1us
in al,KBD_STATUS_PORT ; Read the 8042 Status Port
and al,02h ; Check the Input Buffer Full Flag
loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 02h
gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
dd 0 ; (GDT base gets set above)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; global descriptor table (GDT)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 02h
public GDT_BASE
GDT_BASE:
; null descriptor
NULL_SEL equ $-GDT_BASE
dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
; linear data segment descriptor
LINEAR_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; linear code segment descriptor
LINEAR_CODE_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; system data segment descriptor
SYS_DATA_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; system code segment descriptor
SYS_CODE_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE3_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE4_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE5_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
GDT_END:
align 02h
idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
dd 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 02h
public IDT_BASE
IDT_BASE:
; divide by zero (INT 0)
DIV_ZERO_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; debug exception (INT 1)
DEBUG_EXCEPT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; NMI (INT 2)
NMI_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; soft breakpoint (INT 3)
BREAKPOINT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; overflow (INT 4)
OVERFLOW_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; bounds check (INT 5)
BOUNDS_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; invalid opcode (INT 6)
INVALID_OPCODE_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; device not available (INT 7)
DEV_NOT_AVAIL_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; double fault (INT 8)
DOUBLE_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Coprocessor segment overrun - reserved (INT 9)
RSVD_INTR_SEL1 equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; invalid TSS (INT 0ah)
INVALID_TSS_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; segment not present (INT 0bh)
SEG_NOT_PRESENT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; stack fault (INT 0ch)
STACK_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; general protection (INT 0dh)
GP_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; page fault (INT 0eh)
PAGE_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Intel reserved - do not use (INT 0fh)
RSVD_INTR_SEL2 equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; floating point error (INT 10h)
FLT_POINT_ERR_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; alignment check (INT 11h)
ALIGNMENT_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; machine check (INT 12h)
MACHINE_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; SIMD floating-point exception (INT 13h)
SIMD_EXCEPTION_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
db (85 * 8) dup(0)
; IRQ 0 (System timer) - (INT 68h)
IRQ0_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 1 (8042 Keyboard controller) - (INT 69h)
IRQ1_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
IRQ2_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 3 (COM 2) - (INT 6bh)
IRQ3_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 4 (COM 1) - (INT 6ch)
IRQ4_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 5 (LPT 2) - (INT 6dh)
IRQ5_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 6 (Floppy controller) - (INT 6eh)
IRQ6_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 7 (LPT 1) - (INT 6fh)
IRQ7_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 8 (RTC Alarm) - (INT 70h)
IRQ8_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 9 - (INT 71h)
IRQ9_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 10 - (INT 72h)
IRQ10_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 11 - (INT 73h)
IRQ11_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 12 (PS/2 mouse) - (INT 74h)
IRQ12_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 13 (Floating point error) - (INT 75h)
IRQ13_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 14 (Secondary IDE) - (INT 76h)
IRQ14_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 15 (Primary IDE) - (INT 77h)
IRQ15_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
IDT_END:
align 02h
MemoryMapSize dd 0
MemoryMap dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 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
dd 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 0fe0h
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 0ffeh
BlockSignature:
dw 0aa55h
end

View File

@ -0,0 +1,929 @@
;------------------------------------------------------------------------------
;*
;* 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.
;*
;* start32.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
org 0h
Ia32Jump:
jmp BootSectorEntryPoint ; JMP inst - 3 bytes
nop
OemId db "INTEL " ; OemId - 8 bytes
SectorSize dw 0 ; Sector Size - 2 bytes
SectorsPerCluster db 0 ; Sector Per Cluster - 1 byte
ReservedSectors dw 0 ; Reserved Sectors - 2 bytes
NoFats db 0 ; Number of FATs - 1 byte
RootEntries dw 0 ; Root Entries - 2 bytes
Sectors dw 0 ; Number of Sectors - 2 bytes
Media db 0 ; Media - 1 byte
SectorsPerFat16 dw 0 ; Sectors Per FAT for FAT12/FAT16 - 2 byte
SectorsPerTrack dw 0 ; Sectors Per Track - 2 bytes
Heads dw 0 ; Heads - 2 bytes
HiddenSectors dd 0 ; Hidden Sectors - 4 bytes
LargeSectors dd 0 ; 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 0 ; Sectors Per FAT for FAT32 - 4 bytes
ExtFlags dw 0 ; Mirror Flag - 2 bytes
FSVersion dw 0 ; File System Version - 2 bytes
RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes
FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes
BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes
Reserved db 12 dup(0) ; Reserved Field - 12 bytes
PhysicalDrive db 0 ; Physical Drive Number - 1 byte
Reserved1 db 0 ; Reserved Field - 1 byte
Signature db 0 ; Extended Boot Signature - 1 byte
VolId db " " ; Volume Serial Number - 4 bytes
FatLabel db " " ; Volume Label - 11 bytes
FileSystemType db "FAT32 " ; File System Type - 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
mov bp,07c00h
push cx
; Read Efivar.bin
; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
mov ax,01900h
mov es,ax
test dx,dx
jnz CheckVarStoreSize
mov al,1
NoVarStore:
push es
; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
mov byte ptr es:[4],al
jmp SaveVolumeId
CheckVarStoreSize:
mov di,dx
cmp dword ptr ds:[di+2], 04000h
mov al,2
jne NoVarStore
LoadVarStore:
mov al,0
mov byte ptr es:[4],al
mov cx,word ptr[di]
; ES:DI = 1500:0
xor di,di
push es
mov ax,01500h
mov es,ax
call ReadFile
SaveVolumeId:
pop es
mov ax,word ptr [bp+VolId]
mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
mov ax,word ptr [bp+VolId+2]
mov word ptr es:[2],ax
; Read Efildr
pop cx
; cx = Start Cluster of Efildr -> BS.com has filled already
; ES:DI = 2000:0, first cluster will be read again
xor di,di ; di = 0
mov ax,02000h
mov es,ax
call ReadFile
mov ax,cs
mov word ptr cs:[JumpSegment],ax
JumpFarInstruction:
db 0eah
JumpOffset:
dw 0200h
JumpSegment:
dw 2000h
; ****************************************************************************
; 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
mov si,1 ; NumberOfClusters = 1
push cx ; Push Start Cluster onto stack
mov dx,0fffh ; CachedFatSectorNumber = 0xfff
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
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:
pop 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
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 edx,edx ; edx = 0
movzx ebx,word ptr [bp] ; bx = MaxSector
div ebx ; ax = StartLBA / MaxSector
inc dx ; dx = (StartLBA % MaxSector) + 1
mov bx,word ptr [bp] ; bx = MaxSector
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:
push cs
pop ds
lea si, [ErrorString]
mov cx, 7
jmp PrintStringAndHalt
PrintStringAndHalt:
mov ax,0b800h
mov es,ax
mov di,160
rep movsw
Halt:
jmp Halt
ErrorString:
db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
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
jmp start
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
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
;
cli
; mov ax,0b800h
; mov es,ax
; mov byte ptr es:[164],'c'
; mov ax,cs
; mov es,ax
db 66h
lgdt fword ptr [gdtr]
db 66h
lidt fword ptr [idtr]
mov eax,cr0
or al,1
mov cr0,eax
mov eax,0008h ; Flat data descriptor
mov ebp,000400000h ; Destination of EFILDR32
mov ebx,000070000h ; Length of copy
JUMP:
; jmp far 0010:00020000
db 066h
db 0eah
dd 000020000h
dw 00010h
Empty8042InputBuffer:
mov cx,0
Empty8042Loop:
out DELAY_PORT,ax ; Delay 1us
in al,KBD_STATUS_PORT ; Read the 8042 Status Port
and al,02h ; Check the Input Buffer Full Flag
loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 02h
gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
dd 0 ; (GDT base gets set above)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; global descriptor table (GDT)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 02h
public GDT_BASE
GDT_BASE:
; null descriptor
NULL_SEL equ $-GDT_BASE
dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
; linear data segment descriptor
LINEAR_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; linear code segment descriptor
LINEAR_CODE_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; system data segment descriptor
SYS_DATA_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; system code segment descriptor
SYS_CODE_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE3_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE4_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE5_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
GDT_END:
align 02h
idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
dd 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 02h
public IDT_BASE
IDT_BASE:
; divide by zero (INT 0)
DIV_ZERO_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; debug exception (INT 1)
DEBUG_EXCEPT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; NMI (INT 2)
NMI_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; soft breakpoint (INT 3)
BREAKPOINT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; overflow (INT 4)
OVERFLOW_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; bounds check (INT 5)
BOUNDS_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; invalid opcode (INT 6)
INVALID_OPCODE_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; device not available (INT 7)
DEV_NOT_AVAIL_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; double fault (INT 8)
DOUBLE_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Coprocessor segment overrun - reserved (INT 9)
RSVD_INTR_SEL1 equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; invalid TSS (INT 0ah)
INVALID_TSS_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; segment not present (INT 0bh)
SEG_NOT_PRESENT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; stack fault (INT 0ch)
STACK_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; general protection (INT 0dh)
GP_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; page fault (INT 0eh)
PAGE_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Intel reserved - do not use (INT 0fh)
RSVD_INTR_SEL2 equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; floating point error (INT 10h)
FLT_POINT_ERR_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; alignment check (INT 11h)
ALIGNMENT_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; machine check (INT 12h)
MACHINE_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; SIMD floating-point exception (INT 13h)
SIMD_EXCEPTION_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
db (85 * 8) dup(0)
; IRQ 0 (System timer) - (INT 68h)
IRQ0_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 1 (8042 Keyboard controller) - (INT 69h)
IRQ1_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
IRQ2_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 3 (COM 2) - (INT 6bh)
IRQ3_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 4 (COM 1) - (INT 6ch)
IRQ4_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 5 (LPT 2) - (INT 6dh)
IRQ5_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 6 (Floppy controller) - (INT 6eh)
IRQ6_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 7 (LPT 1) - (INT 6fh)
IRQ7_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 8 (RTC Alarm) - (INT 70h)
IRQ8_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 9 - (INT 71h)
IRQ9_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 10 - (INT 72h)
IRQ10_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 11 - (INT 73h)
IRQ11_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 12 (PS/2 mouse) - (INT 74h)
IRQ12_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 13 (Floating point error) - (INT 75h)
IRQ13_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 14 (Secondary IDE) - (INT 76h)
IRQ14_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 15 (Primary IDE) - (INT 77h)
IRQ15_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
IDT_END:
align 02h
MemoryMapSize dd 0
MemoryMap dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 0,0,0,0,0,0,0,0
dd 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
dd 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 0fe0h
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 0ffeh
BlockSignature:
dw 0aa55h
end

File diff suppressed because it is too large Load Diff

1151
DuetPkg/CpuDxe/Cpu.c Normal file

File diff suppressed because it is too large Load Diff

25
DuetPkg/CpuDxe/Cpu.dxs Normal file
View File

@ -0,0 +1,25 @@
/*++
Copyright (c) 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.
Module Name:
Cpu.dxs
Abstract:
Dependency expression source file.
--*/
#include "EfiDepex.h"
#include EFI_PROTOCOL_DEFINITION (Legacy8259)
DEPENDENCY_START
EFI_LEGACY_8259_PROTOCOL_GUID
DEPENDENCY_END

53
DuetPkg/CpuDxe/Cpu.inf Normal file
View File

@ -0,0 +1,53 @@
#/*++
#
# Copyright (c) 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.
#
# Module Name:
# Cpu.inf
#
# Abstract:
#
#--*/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = Cpu
FILE_GUID = 10527025-78B2-4d3e-A9DF-41E75C220F5A
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = InitializeCpu
[Packages]
DuetPkg/DuetPkg.dec
MdePkg/MdePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
[LibraryClasses]
UefiDriverEntryPoint
PrintLib
UefiBootServicesTableLib
[Sources.IA32]
IA32/CpuInterrupt.asm
[Sources.X64]
X64/CpuInterrupt.asm
[Sources.common]
Cpu.c
CpuDxe.h
[Protocols]
gEfiCpuArchProtocolGuid
gEfiLegacyBiosThunkProtocolGuid
gEfiLegacy8259ProtocolGuid

148
DuetPkg/CpuDxe/CpuDxe.h Normal file
View File

@ -0,0 +1,148 @@
/*++
Copyright (c) 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.
Module Name:
CpuDxe.h
Abstract:
--*/
#ifndef _CPU_DXE_H
#define _CPU_DXE_H
#include <PiDxe.h>
#include <Protocol/Cpu.h>
#include <Protocol/Legacy8259.h>
#include <Protocol/LegacyBios.h>
#include <Protocol/LegacyBiosThunk.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiBootServicesTableLib.h>
#define CPU_EXCEPTION_DEBUG_OUTPUT 1
#define CPU_EXCEPTION_VGA_SWITCH 1
#define INTERRUPT_VECTOR_NUMBER 0x100
//
// Print primitives
//
//#define LEFT_JUSTIFY 0x01
#define PREFIX_SIGN 0x02
#define PREFIX_BLANK 0x04
//#define COMMA_TYPE 0x08
#define LONG_TYPE 0x10
//#define PREFIX_ZERO 0x20
#define OUTPUT_UNICODE 0x40
//#define RADIX_HEX 0x80
#define FORMAT_UNICODE 0x100
#define PAD_TO_WIDTH 0x200
#define ARGUMENT_UNICODE 0x400
#define PRECISION 0x800
#define ARGUMENT_REVERSED 0x1000
//
// Function declarations
//
EFI_STATUS
EFIAPI
InitializeCpu (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
EFI_STATUS
EFIAPI
CpuFlushCpuDataCache (
IN EFI_CPU_ARCH_PROTOCOL *This,
IN EFI_PHYSICAL_ADDRESS Start,
IN UINT64 Length,
IN EFI_CPU_FLUSH_TYPE FlushType
);
EFI_STATUS
EFIAPI
CpuEnableInterrupt (
IN EFI_CPU_ARCH_PROTOCOL *This
);
EFI_STATUS
EFIAPI
CpuDisableInterrupt (
IN EFI_CPU_ARCH_PROTOCOL *This
);
EFI_STATUS
EFIAPI
CpuGetInterruptState (
IN EFI_CPU_ARCH_PROTOCOL *This,
OUT BOOLEAN *State
);
EFI_STATUS
EFIAPI
CpuInit (
IN EFI_CPU_ARCH_PROTOCOL *This,
IN EFI_CPU_INIT_TYPE InitType
);
EFI_STATUS
EFIAPI
CpuRegisterInterruptHandler (
IN EFI_CPU_ARCH_PROTOCOL *This,
IN EFI_EXCEPTION_TYPE InterruptType,
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
);
EFI_STATUS
EFIAPI
CpuGetTimerValue (
IN EFI_CPU_ARCH_PROTOCOL *This,
IN UINT32 TimerIndex,
OUT UINT64 *TimerValue,
OUT UINT64 *TimerPeriod OPTIONAL
);
EFI_STATUS
EFIAPI
CpuSetMemoryAttributes(
IN EFI_CPU_ARCH_PROTOCOL *This,
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN UINT64 Attributes
);
VOID
InstallInterruptHandler (
UINTN Vector,
VOID (*Handler)(VOID)
);
VOID
SystemExceptionHandler (
VOID
);
VOID
SystemTimerHandler (
VOID
);
VOID
InitDescriptor (
VOID
);
#endif

View File

@ -0,0 +1,835 @@
TITLE CpuInterrupt.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.
;*
;* CpuInterrupt.asm
;*
;* Abstract:
;*
;------------------------------------------------------------------------------
.686p
.model flat, C
PUBLIC SystemTimerHandler
PUBLIC SystemExceptionHandler
EXTERNDEF mExceptionCodeSize:DWORD
.code
.stack
.MMX
.XMM
EXTERN TimerHandler: NEAR
EXTERN ExceptionHandler: NEAR
EXTERN mTimerVector: DWORD
mExceptionCodeSize DD 9
InitDescriptor PROC C
lea eax, [GDT_BASE] ; EAX=PHYSICAL address of gdt
mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
lgdt fword ptr [gdtr]
lea eax, [IDT_BASE] ; EAX=PHYSICAL address of idt
mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
lidt fword ptr [idtr]
ret
InitDescriptor ENDP
; VOID
; InstallInterruptHandler (
; UINTN Vector,
; VOID (*Handler)(VOID)
; )
InstallInterruptHandler PROC C \
Vector:DWORD, \
Handler:DWORD
push edi
pushfd ; save eflags
cli ; turn off interrupts
sub esp, 6 ; open some space on the stack
mov edi, esp
sidt es:[edi] ; get fword address of IDT
mov edi, es:[edi+2] ; move offset of IDT into EDI
add esp, 6 ; correct stack
mov eax, Vector ; Get vector number
shl eax, 3 ; multiply by 8 to get offset
add edi, eax ; add to IDT base to get entry
mov eax, Handler ; load new address into IDT entry
mov word ptr es:[edi], ax ; write bits 15..0 of offset
shr eax, 16 ; use ax to copy 31..16 to descriptors
mov word ptr es:[edi+6], ax ; write bits 31..16 of offset
popfd ; restore flags (possible enabling interrupts)
pop edi
ret
InstallInterruptHandler ENDP
JmpCommonIdtEntry macro
; jmp commonIdtEntry - this must be hand coded to keep the assembler from
; using a 8 bit reletive jump when the entries are
; within 255 bytes of the common entry. This must
; be done to maintain the consistency of the size
; of entry points...
db 0e9h ; jmp 16 bit reletive
dd commonIdtEntry - $ - 4 ; offset to jump to
endm
align 02h
SystemExceptionHandler PROC
INT0:
push 0h ; push error code place holder on the stack
push 0h
JmpCommonIdtEntry
; db 0e9h ; jmp 16 bit reletive
; dd commonIdtEntry - $ - 4 ; offset to jump to
INT1:
push 0h ; push error code place holder on the stack
push 1h
JmpCommonIdtEntry
INT2:
push 0h ; push error code place holder on the stack
push 2h
JmpCommonIdtEntry
INT3:
push 0h ; push error code place holder on the stack
push 3h
JmpCommonIdtEntry
INT4:
push 0h ; push error code place holder on the stack
push 4h
JmpCommonIdtEntry
INT5:
push 0h ; push error code place holder on the stack
push 5h
JmpCommonIdtEntry
INT6:
push 0h ; push error code place holder on the stack
push 6h
JmpCommonIdtEntry
INT7:
push 0h ; push error code place holder on the stack
push 7h
JmpCommonIdtEntry
INT8:
; Double fault causes an error code to be pushed so no phony push necessary
nop
nop
push 8h
JmpCommonIdtEntry
INT9:
push 0h ; push error code place holder on the stack
push 9h
JmpCommonIdtEntry
INT10:
; Invalid TSS causes an error code to be pushed so no phony push necessary
nop
nop
push 10
JmpCommonIdtEntry
INT11:
; Segment Not Present causes an error code to be pushed so no phony push necessary
nop
nop
push 11
JmpCommonIdtEntry
INT12:
; Stack fault causes an error code to be pushed so no phony push necessary
nop
nop
push 12
JmpCommonIdtEntry
INT13:
; GP fault causes an error code to be pushed so no phony push necessary
nop
nop
push 13
JmpCommonIdtEntry
INT14:
; Page fault causes an error code to be pushed so no phony push necessary
nop
nop
push 14
JmpCommonIdtEntry
INT15:
push 0h ; push error code place holder on the stack
push 15
JmpCommonIdtEntry
INT16:
push 0h ; push error code place holder on the stack
push 16
JmpCommonIdtEntry
INT17:
; Alignment check causes an error code to be pushed so no phony push necessary
nop
nop
push 17
JmpCommonIdtEntry
INT18:
push 0h ; push error code place holder on the stack
push 18
JmpCommonIdtEntry
INT19:
push 0h ; push error code place holder on the stack
push 19
JmpCommonIdtEntry
INTUnknown:
REPEAT (32 - 20)
push 0h ; push error code place holder on the stack
; push xxh ; push vector number
db 06ah
db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
JmpCommonIdtEntry
ENDM
SystemExceptionHandler ENDP
SystemTimerHandler PROC
push 0
push mTimerVector
JmpCommonIdtEntry
SystemTimerHandler ENDP
commonIdtEntry:
; +---------------------+
; + EFlags +
; +---------------------+
; + CS +
; +---------------------+
; + EIP +
; +---------------------+
; + Error Code +
; +---------------------+
; + Vector Number +
; +---------------------+
; + EBP +
; +---------------------+ <-- EBP
cli
push ebp
mov ebp, esp
;
; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
; is 16-byte aligned
;
and esp, 0fffffff0h
sub esp, 12
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
push eax
push ecx
push edx
push ebx
lea ecx, [ebp + 6 * 4]
push ecx ; ESP
push dword ptr [ebp] ; EBP
push esi
push edi
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
mov eax, ss
push eax
movzx eax, word ptr [ebp + 4 * 4]
push eax
mov eax, ds
push eax
mov eax, es
push eax
mov eax, fs
push eax
mov eax, gs
push eax
;; UINT32 Eip;
push dword ptr [ebp + 3 * 4]
;; UINT32 Gdtr[2], Idtr[2];
sub esp, 8
sidt fword ptr [esp]
sub esp, 8
sgdt fword ptr [esp]
;; UINT32 Ldtr, Tr;
xor eax, eax
str ax
push eax
sldt ax
push eax
;; UINT32 EFlags;
push dword ptr [ebp + 5 * 4]
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
mov eax, cr4
or eax, 208h
mov cr4, eax
push eax
mov eax, cr3
push eax
mov eax, cr2
push eax
xor eax, eax
push eax
mov eax, cr0
push eax
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
mov eax, dr7
push eax
;; clear Dr7 while executing debugger itself
xor eax, eax
mov dr7, eax
mov eax, dr6
push eax
;; insure all status bits in dr6 are clear...
xor eax, eax
mov dr6, eax
mov eax, dr3
push eax
mov eax, dr2
push eax
mov eax, dr1
push eax
mov eax, dr0
push eax
;; FX_SAVE_STATE_IA32 FxSaveState;
sub esp, 512
mov edi, esp
db 0fh, 0aeh, 00000111y ;fxsave [edi]
;; UINT32 ExceptionData;
push dword ptr [ebp + 2 * 4]
;; Prepare parameter and call
mov edx, esp
push edx
mov eax, dword ptr [ebp + 1 * 4]
push eax
cmp eax, 32
jb CallException
call TimerHandler
jmp ExceptionDone
CallException:
call ExceptionHandler
ExceptionDone:
add esp, 8
cli
;; UINT32 ExceptionData;
add esp, 4
;; FX_SAVE_STATE_IA32 FxSaveState;
mov esi, esp
db 0fh, 0aeh, 00001110y ; fxrstor [esi]
add esp, 512
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
pop eax
mov dr0, eax
pop eax
mov dr1, eax
pop eax
mov dr2, eax
pop eax
mov dr3, eax
;; skip restore of dr6. We cleared dr6 during the context save.
add esp, 4
pop eax
mov dr7, eax
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
pop eax
mov cr0, eax
add esp, 4 ; not for Cr1
pop eax
mov cr2, eax
pop eax
mov cr3, eax
pop eax
mov cr4, eax
;; UINT32 EFlags;
pop dword ptr [ebp + 5 * 4]
;; UINT32 Ldtr, Tr;
;; UINT32 Gdtr[2], Idtr[2];
;; Best not let anyone mess with these particular registers...
add esp, 24
;; UINT32 Eip;
pop dword ptr [ebp + 3 * 4]
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
;; NOTE - modified segment registers could hang the debugger... We
;; could attempt to insulate ourselves against this possibility,
;; but that poses risks as well.
;;
pop gs
pop fs
pop es
pop ds
pop dword ptr [ebp + 4 * 4]
pop ss
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
pop edi
pop esi
add esp, 4 ; not for ebp
add esp, 4 ; not for esp
pop ebx
pop edx
pop ecx
pop eax
mov esp, ebp
pop ebp
add esp, 8
iretd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 02h
gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
dd 0 ; (GDT base gets set above)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; global descriptor table (GDT)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 02h
public GDT_BASE
GDT_BASE:
; null descriptor
NULL_SEL equ $-GDT_BASE
dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
; linear data segment descriptor
LINEAR_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; linear code segment descriptor
LINEAR_CODE_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; system data segment descriptor
SYS_DATA_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; system code segment descriptor
SYS_CODE_SEL equ $-GDT_BASE
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE3_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE4_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE5_SEL equ $-GDT_BASE
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
GDT_END:
align 02h
idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
dd 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 02h
public IDT_BASE
IDT_BASE:
; divide by zero (INT 0)
DIV_ZERO_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; debug exception (INT 1)
DEBUG_EXCEPT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; NMI (INT 2)
NMI_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; soft breakpoint (INT 3)
BREAKPOINT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; overflow (INT 4)
OVERFLOW_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; bounds check (INT 5)
BOUNDS_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; invalid opcode (INT 6)
INVALID_OPCODE_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; device not available (INT 7)
DEV_NOT_AVAIL_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; double fault (INT 8)
DOUBLE_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Coprocessor segment overrun - reserved (INT 9)
RSVD_INTR_SEL1 equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; invalid TSS (INT 0ah)
INVALID_TSS_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; segment not present (INT 0bh)
SEG_NOT_PRESENT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; stack fault (INT 0ch)
STACK_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; general protection (INT 0dh)
GP_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; page fault (INT 0eh)
PAGE_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Intel reserved - do not use (INT 0fh)
RSVD_INTR_SEL2 equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; floating point error (INT 10h)
FLT_POINT_ERR_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
; alignment check (INT 11h)
ALIGNMENT_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; machine check (INT 12h)
MACHINE_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; SIMD floating-point exception (INT 13h)
SIMD_EXCEPTION_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
REPEAT (32 - 20)
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
ENDM
; 72 unspecified descriptors
db (72 * 8) dup(0)
; IRQ 0 (System timer) - (INT 68h)
IRQ0_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 1 (8042 Keyboard controller) - (INT 69h)
IRQ1_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
IRQ2_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 3 (COM 2) - (INT 6bh)
IRQ3_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 4 (COM 1) - (INT 6ch)
IRQ4_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 5 (LPT 2) - (INT 6dh)
IRQ5_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 6 (Floppy controller) - (INT 6eh)
IRQ6_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 7 (LPT 1) - (INT 6fh)
IRQ7_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 8 (RTC Alarm) - (INT 70h)
IRQ8_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 9 - (INT 71h)
IRQ9_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 10 - (INT 72h)
IRQ10_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 11 - (INT 73h)
IRQ11_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 12 (PS/2 mouse) - (INT 74h)
IRQ12_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 13 (Floating point error) - (INT 75h)
IRQ13_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 14 (Secondary IDE) - (INT 76h)
IRQ14_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
; IRQ 15 (Primary IDE) - (INT 77h)
IRQ15_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
db (1 * 8) dup(0)
IDT_END:
END

View File

@ -0,0 +1,949 @@
TITLE CpuInterrupt.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.
;*
;* CpuInterrupt.asm
;*
;* Abstract:
;*
;------------------------------------------------------------------------------
EXTERNDEF mExceptionCodeSize:DWORD
.code
EXTERN TimerHandler: FAR
EXTERN ExceptionHandler: NEAR
EXTERN mTimerVector: QWORD
mExceptionCodeSize DD 9
InitDescriptor PROC
lea rax, [GDT_BASE] ; RAX=PHYSICAL address of gdt
mov qword ptr [gdtr + 2], rax ; Put address of gdt into the gdtr
lgdt fword ptr [gdtr]
mov rax, 18h
mov gs, rax
mov fs, rax
lea rax, [IDT_BASE] ; RAX=PHYSICAL address of idt
mov qword ptr [idtr + 2], rax ; Put address of idt into the idtr
lidt fword ptr [idtr]
ret
InitDescriptor ENDP
; VOID
; InstallInterruptHandler (
; UINTN Vector, // rcx
; void (*Handler)(void) // rdx
; )
InstallInterruptHandler PROC
push rbx
pushfq ; save eflags
cli ; turn off interrupts
sub rsp, 10h ; open some space on the stack
mov rbx, rsp
sidt [rbx] ; get fword address of IDT
mov rbx, [rbx+2] ; move offset of IDT into RBX
add rsp, 10h ; correct stack
mov rax, rcx ; Get vector number
shl rax, 4 ; multiply by 16 to get offset
add rbx, rax ; add to IDT base to get entry
mov rax, rdx ; load new address into IDT entry
mov word ptr [rbx], ax ; write bits 15..0 of offset
shr rax, 16 ; use ax to copy 31..16 to descriptors
mov word ptr [rbx+6], ax ; write bits 31..16 of offset
shr rax, 16 ; use eax to copy 63..32 to descriptors
mov dword ptr [rbx+8], eax ; write bits 63..32 of offset
popfq ; restore flags (possible enabling interrupts)
pop rbx
ret
InstallInterruptHandler ENDP
JmpCommonIdtEntry macro
; jmp commonIdtEntry - this must be hand coded to keep the assembler from
; using a 8 bit reletive jump when the entries are
; within 255 bytes of the common entry. This must
; be done to maintain the consistency of the size
; of entry points...
db 0e9h ; jmp 16 bit reletive
dd commonIdtEntry - $ - 4 ; offset to jump to
endm
align 02h
SystemExceptionHandler PROC
INT0:
push 0h ; push error code place holder on the stack
push 0h
JmpCommonIdtEntry
; db 0e9h ; jmp 16 bit reletive
; dd commonIdtEntry - $ - 4 ; offset to jump to
INT1:
push 0h ; push error code place holder on the stack
push 1h
JmpCommonIdtEntry
INT2:
push 0h ; push error code place holder on the stack
push 2h
JmpCommonIdtEntry
INT3:
push 0h ; push error code place holder on the stack
push 3h
JmpCommonIdtEntry
INT4:
push 0h ; push error code place holder on the stack
push 4h
JmpCommonIdtEntry
INT5:
push 0h ; push error code place holder on the stack
push 5h
JmpCommonIdtEntry
INT6:
push 0h ; push error code place holder on the stack
push 6h
JmpCommonIdtEntry
INT7:
push 0h ; push error code place holder on the stack
push 7h
JmpCommonIdtEntry
INT8:
; Double fault causes an error code to be pushed so no phony push necessary
nop
nop
push 8h
JmpCommonIdtEntry
INT9:
push 0h ; push error code place holder on the stack
push 9h
JmpCommonIdtEntry
INT10:
; Invalid TSS causes an error code to be pushed so no phony push necessary
nop
nop
push 10
JmpCommonIdtEntry
INT11:
; Segment Not Present causes an error code to be pushed so no phony push necessary
nop
nop
push 11
JmpCommonIdtEntry
INT12:
; Stack fault causes an error code to be pushed so no phony push necessary
nop
nop
push 12
JmpCommonIdtEntry
INT13:
; GP fault causes an error code to be pushed so no phony push necessary
nop
nop
push 13
JmpCommonIdtEntry
INT14:
; Page fault causes an error code to be pushed so no phony push necessary
nop
nop
push 14
JmpCommonIdtEntry
INT15:
push 0h ; push error code place holder on the stack
push 15
JmpCommonIdtEntry
INT16:
push 0h ; push error code place holder on the stack
push 16
JmpCommonIdtEntry
INT17:
; Alignment check causes an error code to be pushed so no phony push necessary
nop
nop
push 17
JmpCommonIdtEntry
INT18:
push 0h ; push error code place holder on the stack
push 18
JmpCommonIdtEntry
INT19:
push 0h ; push error code place holder on the stack
push 19
JmpCommonIdtEntry
INTUnknown:
REPEAT (32 - 20)
push 0h ; push error code place holder on the stack
; push xxh ; push vector number
db 06ah
db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
JmpCommonIdtEntry
ENDM
SystemExceptionHandler ENDP
SystemTimerHandler PROC
push 0
push mTimerVector
JmpCommonIdtEntry
SystemTimerHandler ENDP
commonIdtEntry:
; +---------------------+ <-- 16-byte aligned ensured by processor
; + Old SS +
; +---------------------+
; + Old RSP +
; +---------------------+
; + RFlags +
; +---------------------+
; + CS +
; +---------------------+
; + RIP +
; +---------------------+
; + Error Code +
; +---------------------+
; + Vector Number +
; +---------------------+
; + RBP +
; +---------------------+ <-- RBP, 16-byte aligned
cli
push rbp
mov rbp, rsp
;
; Since here the stack pointer is 16-byte aligned, so
; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
; is 16-byte aligned
;
;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
push r15
push r14
push r13
push r12
push r11
push r10
push r9
push r8
push rax
push rcx
push rdx
push rbx
push qword ptr [rbp + 6 * 8] ; RSP
push qword ptr [rbp] ; RBP
push rsi
push rdi
;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
movzx rax, word ptr [rbp + 7 * 8]
push rax ; for ss
movzx rax, word ptr [rbp + 4 * 8]
push rax ; for cs
mov rax, ds
push rax
mov rax, es
push rax
mov rax, fs
push rax
mov rax, gs
push rax
;; UINT64 Rip;
push qword ptr [rbp + 3 * 8]
;; UINT64 Gdtr[2], Idtr[2];
sub rsp, 16
sidt fword ptr [rsp]
sub rsp, 16
sgdt fword ptr [rsp]
;; UINT64 Ldtr, Tr;
xor rax, rax
str ax
push rax
sldt ax
push rax
;; UINT64 RFlags;
push qword ptr [rbp + 5 * 8]
;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
mov rax, cr8
push rax
mov rax, cr4
or rax, 208h
mov cr4, rax
push rax
mov rax, cr3
push rax
mov rax, cr2
push rax
xor rax, rax
push rax
mov rax, cr0
push rax
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
mov rax, dr7
push rax
;; clear Dr7 while executing debugger itself
xor rax, rax
mov dr7, rax
mov rax, dr6
push rax
;; insure all status bits in dr6 are clear...
xor rax, rax
mov dr6, rax
mov rax, dr3
push rax
mov rax, dr2
push rax
mov rax, dr1
push rax
mov rax, dr0
push rax
;; FX_SAVE_STATE_X64 FxSaveState;
sub rsp, 512
mov rdi, rsp
db 0fh, 0aeh, 00000111y ;fxsave [rdi]
;; UINT32 ExceptionData;
push qword ptr [rbp + 2 * 8]
;; call into exception handler
;; Prepare parameter and call
mov rcx, qword ptr [rbp + 1 * 8]
mov rdx, rsp
;
; Per X64 calling convention, allocate maximum parameter stack space
; and make sure RSP is 16-byte aligned
;
sub rsp, 4 * 8 + 8
cmp rcx, 32
jb CallException
call TimerHandler
jmp ExceptionDone
CallException:
call ExceptionHandler
ExceptionDone:
add rsp, 4 * 8 + 8
cli
;; UINT64 ExceptionData;
add rsp, 8
;; FX_SAVE_STATE_X64 FxSaveState;
mov rsi, rsp
db 0fh, 0aeh, 00001110y ; fxrstor [rsi]
add rsp, 512
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
pop rax
mov dr0, rax
pop rax
mov dr1, rax
pop rax
mov dr2, rax
pop rax
mov dr3, rax
;; skip restore of dr6. We cleared dr6 during the context save.
add rsp, 8
pop rax
mov dr7, rax
;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
pop rax
mov cr0, rax
add rsp, 8 ; not for Cr1
pop rax
mov cr2, rax
pop rax
mov cr3, rax
pop rax
mov cr4, rax
pop rax
mov cr8, rax
;; UINT64 RFlags;
pop qword ptr [rbp + 5 * 8]
;; UINT64 Ldtr, Tr;
;; UINT64 Gdtr[2], Idtr[2];
;; Best not let anyone mess with these particular registers...
add rsp, 48
;; UINT64 Rip;
pop qword ptr [rbp + 3 * 8]
;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
pop rax
; mov gs, rax ; not for gs
pop rax
; mov fs, rax ; not for fs
; (X64 will not use fs and gs, so we do not restore it)
pop rax
mov es, rax
pop rax
mov ds, rax
pop qword ptr [rbp + 4 * 8] ; for cs
pop qword ptr [rbp + 7 * 8] ; for ss
;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
pop rdi
pop rsi
add rsp, 8 ; not for rbp
pop qword ptr [rbp + 6 * 8] ; for rsp
pop rbx
pop rdx
pop rcx
pop rax
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
mov rsp, rbp
pop rbp
add rsp, 16
iretq
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 010h
gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
dq 0 ; (GDT base gets set above)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; global descriptor table (GDT)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 010h
public GDT_BASE
GDT_BASE:
; null descriptor
NULL_SEL equ $-GDT_BASE ; Selector [0x0]
dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
; linear data segment descriptor
LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; linear code segment descriptor
LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; system data segment descriptor
SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; system code segment descriptor
SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
; spare segment descriptor
SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
;
; system data segment descriptor
;
SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
db 0CFh ; G | D | L | AVL | Segment [19..16]
db 0
;
; system code segment descriptor
;
SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
db 0AFh ; G | D | L | AVL | Segment [19..16]
db 0
; spare segment descriptor
SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
dw 0 ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 32-bit
db 0
GDT_END:
align 02h
idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
dq 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 02h
public IDT_BASE
IDT_BASE:
; divide by zero (INT 0)
DIV_ZERO_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; debug exception (INT 1)
DEBUG_EXCEPT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; NMI (INT 2)
NMI_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; soft breakpoint (INT 3)
BREAKPOINT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; overflow (INT 4)
OVERFLOW_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; bounds check (INT 5)
BOUNDS_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; invalid opcode (INT 6)
INVALID_OPCODE_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; device not available (INT 7)
DEV_NOT_AVAIL_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; double fault (INT 8)
DOUBLE_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; Coprocessor segment overrun - reserved (INT 9)
RSVD_INTR_SEL1 equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; invalid TSS (INT 0ah)
INVALID_TSS_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; segment not present (INT 0bh)
SEG_NOT_PRESENT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; stack fault (INT 0ch)
STACK_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; general protection (INT 0dh)
GP_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; page fault (INT 0eh)
PAGE_FAULT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; Intel reserved - do not use (INT 0fh)
RSVD_INTR_SEL2 equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; floating point error (INT 10h)
FLT_POINT_ERR_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; alignment check (INT 11h)
ALIGNMENT_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; machine check (INT 12h)
MACHINE_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; SIMD floating-point exception (INT 13h)
SIMD_EXCEPTION_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
REPEAT (32 - 20)
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
ENDM
; 72 unspecified descriptors
db (72 * 16) dup(0)
; IRQ 0 (System timer) - (INT 68h)
IRQ0_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 1 (8042 Keyboard controller) - (INT 69h)
IRQ1_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
IRQ2_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 3 (COM 2) - (INT 6bh)
IRQ3_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 4 (COM 1) - (INT 6ch)
IRQ4_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 5 (LPT 2) - (INT 6dh)
IRQ5_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 6 (Floppy controller) - (INT 6eh)
IRQ6_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 7 (LPT 1) - (INT 6fh)
IRQ7_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 8 (RTC Alarm) - (INT 70h)
IRQ8_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 9 - (INT 71h)
IRQ9_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 10 - (INT 72h)
IRQ10_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 11 - (INT 73h)
IRQ11_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 12 (PS/2 mouse) - (INT 74h)
IRQ12_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 13 (Floating point error) - (INT 75h)
IRQ13_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 14 (Secondary IDE) - (INT 76h)
IRQ14_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; IRQ 15 (Primary IDE) - (INT 77h)
IRQ15_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
db (1 * 16) dup(0)
IDT_END:
align 02h
END

533
DuetPkg/CpuIoDxe/CpuIo.c Normal file
View File

@ -0,0 +1,533 @@
/*++
Copyright (c) 2004 - 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.
Module Name:
CpuIo.c
Abstract:
This is the code that publishes the CPU I/O Protocol.
The intent herein is to have a single I/O service that can load
as early as possible, extend into runtime, and be layered upon by
the implementations of architectural protocols and the PCI Root
Bridge I/O Protocol.
--*/
#include "CpuIo.h"
#include "CpuIoAccess.h"
#define IA32_MAX_IO_ADDRESS 0xFFFF
EFI_CPU_IO_PROTOCOL mCpuIo = {
{
CpuMemoryServiceRead,
CpuMemoryServiceWrite
},
{
CpuIoServiceRead,
CpuIoServiceWrite
}
};
STATIC
EFI_STATUS
CpuIoMemRW (
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINTN Count,
IN BOOLEAN DestinationStrideFlag,
OUT PTR Destination,
IN BOOLEAN SourceStrideFlag,
IN PTR Source
)
/*++
Routine Description:
Private service to perform memory mapped I/O read/write
Arguments:
Width - Width of the memory mapped I/O operation
Count - Count of the number of accesses to perform
DestinationStrideFlag - Boolean flag indicates if the destination is to be incremented
Destination - Destination of the memory mapped I/O operation
SourceStrideFlag - Boolean flag indicates if the source is to be incremented
Source - Source of the memory mapped I/O operation
Returns:
EFI_SUCCESS - Successful operation
EFI_INVALID_PARAMETER - Width is invalid
--*/
{
UINTN Stride;
UINTN DestinationStride;
UINTN SourceStride;
Width = Width & 0x03;
Stride = (UINTN)1 << Width;
DestinationStride = DestinationStrideFlag ? Stride : 0;
SourceStride = SourceStrideFlag ? Stride : 0;
//
// Loop for each iteration and move the data
//
switch (Width) {
case EfiCpuIoWidthUint8:
for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {
MemoryFence();
*Destination.ui8 = *Source.ui8;
MemoryFence();
}
break;
case EfiCpuIoWidthUint16:
for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {
MemoryFence ();
*Destination.ui16 = *Source.ui16;
MemoryFence ();
}
break;
case EfiCpuIoWidthUint32:
for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {
MemoryFence ();
*Destination.ui32 = *Source.ui32;
MemoryFence ();
}
break;
case EfiCpuIoWidthUint64:
for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {
MemoryFence ();
*Destination.ui64 = *Source.ui64;
MemoryFence ();
}
break;
default:
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
CpuMemoryServiceRead (
IN EFI_CPU_IO_PROTOCOL *This,
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
OUT VOID *Buffer
)
/*++
Routine Description:
Perform the memory mapped I/O read service
Arguments:
This - Pointer to an instance of the CPU I/O Protocol
Width - Width of the memory mapped I/O operation
Address - Base address of the memory mapped I/O operation
Count - Count of the number of accesses to perform
Buffer - Pointer to the destination buffer to store the results
Returns:
EFI_SUCCESS - The data was read.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_INVALID_PARAMETER - Buffer is NULL.
EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
EFI_UNSUPPORTED - The address range specified by Address, Width,
and Count is not valid.
--*/
{
PTR Source;
PTR Destination;
EFI_STATUS Status;
Status = CpuIoCheckParameter (Width, Address, Count, Buffer, EFI_MAX_ADDRESS);
if (EFI_ERROR (Status)) {
return Status;
}
Destination.buf = Buffer;
Source.buf = (VOID *) (UINTN) Address;
if (Width >= EfiCpuIoWidthUint8 && Width <= EfiCpuIoWidthUint64) {
return CpuIoMemRW (Width, Count, TRUE, Destination, TRUE, Source);
}
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
return CpuIoMemRW (Width, Count, TRUE, Destination, FALSE, Source);
}
if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
return CpuIoMemRW (Width, Count, FALSE, Destination, TRUE, Source);
}
return EFI_INVALID_PARAMETER;
}
EFI_STATUS
EFIAPI
CpuMemoryServiceWrite (
IN EFI_CPU_IO_PROTOCOL *This,
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN VOID *Buffer
)
/*++
Routine Description:
Perform the memory mapped I/O write service
Arguments:
This - Pointer to an instance of the CPU I/O Protocol
Width - Width of the memory mapped I/O operation
Address - Base address of the memory mapped I/O operation
Count - Count of the number of accesses to perform
Buffer - Pointer to the source buffer from which to write data
Returns:
EFI_SUCCESS - The data was written.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_INVALID_PARAMETER - Buffer is NULL.
EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
EFI_UNSUPPORTED - The address range specified by Address, Width,
and Count is not valid.
--*/
{
PTR Source;
PTR Destination;
EFI_STATUS Status;
Status = CpuIoCheckParameter (Width, Address, Count, Buffer, EFI_MAX_ADDRESS);
if (EFI_ERROR (Status)) {
return Status;
}
Destination.buf = (VOID *) (UINTN) Address;
Source.buf = Buffer;
if (Width >= EfiCpuIoWidthUint8 && Width <= EfiCpuIoWidthUint64) {
return CpuIoMemRW (Width, Count, TRUE, Destination, TRUE, Source);
}
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
return CpuIoMemRW (Width, Count, FALSE, Destination, TRUE, Source);
}
if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
return CpuIoMemRW (Width, Count, TRUE, Destination, FALSE, Source);
}
return EFI_INVALID_PARAMETER;
}
EFI_STATUS
EFIAPI
CpuIoServiceRead (
IN EFI_CPU_IO_PROTOCOL *This,
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
OUT VOID *UserBuffer
)
/*++
Routine Description:
Perform the port I/O read service
Arguments:
This - Pointer to an instance of the CPU I/O Protocol
Width - Width of the port I/O operation
Address - Base address of the port I/O operation
Count - Count of the number of accesses to perform
Buffer - Pointer to the destination buffer to store the results
Returns:
EFI_SUCCESS - The data was read.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_INVALID_PARAMETER - Buffer is NULL.
EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
EFI_UNSUPPORTED - The address range specified by Address, Width,
and Count is not valid.
--*/
{
UINTN InStride;
UINTN OutStride;
UINTN Address;
PTR Buffer;
EFI_STATUS Status;
Buffer.buf = (UINT8 *) UserBuffer;
if (Width >= EfiCpuIoWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
Status = CpuIoCheckParameter (Width, UserAddress, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
if (EFI_ERROR (Status)) {
return Status;
}
Address = (UINTN) UserAddress;
InStride = (UINTN)1 << (Width & 0x03);
OutStride = InStride;
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
InStride = 0;
}
if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
OutStride = 0;
}
Width = Width & 0x03;
//
// Loop for each iteration and move the data
//
switch (Width) {
case EfiCpuIoWidthUint8:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
*Buffer.ui8 = CpuIoRead8 ((UINT16) Address);
}
break;
case EfiCpuIoWidthUint16:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
*Buffer.ui16 = CpuIoRead16 ((UINT16) Address);
}
break;
case EfiCpuIoWidthUint32:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
*Buffer.ui32 = CpuIoRead32 ((UINT16) Address);
}
break;
default:
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
CpuIoServiceWrite (
IN EFI_CPU_IO_PROTOCOL *This,
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN VOID *UserBuffer
)
/*++
Routine Description:
Perform the port I/O write service
Arguments:
This - Pointer to an instance of the CPU I/O Protocol
Width - Width of the port I/O operation
Address - Base address of the port I/O operation
Count - Count of the number of accesses to perform
Buffer - Pointer to the source buffer from which to write data
Returns:
EFI_SUCCESS - The data was written.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_INVALID_PARAMETER - Buffer is NULL.
EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
EFI_UNSUPPORTED - The address range specified by Address, Width,
and Count is not valid.
--*/
{
UINTN InStride;
UINTN OutStride;
UINTN Address;
PTR Buffer;
EFI_STATUS Status;
Buffer.buf = (UINT8 *) UserBuffer;
if (Width >= EfiCpuIoWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
Status = CpuIoCheckParameter (Width, UserAddress, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
if (EFI_ERROR (Status)) {
return Status;
}
Address = (UINTN) UserAddress;
InStride = (UINTN)1 << (Width & 0x03);
OutStride = InStride;
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
InStride = 0;
}
if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
OutStride = 0;
}
Width = Width & 0x03;
//
// Loop for each iteration and move the data
//
switch (Width) {
case EfiCpuIoWidthUint8:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
CpuIoWrite8 ((UINT16) Address, *Buffer.ui8);
}
break;
case EfiCpuIoWidthUint16:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
CpuIoWrite16 ((UINT16) Address, *Buffer.ui16);
}
break;
case EfiCpuIoWidthUint32:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
CpuIoWrite32 ((UINT16) Address, *Buffer.ui32);
}
break;
default:
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
CpuIoInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
CpuIo driver entry point.
Arguments:
ImageHandle - The firmware allocated handle for the EFI image.
SystemTable - A pointer to the EFI System Table.
Returns:
EFI_SUCCESS - The driver was initialized.
EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
--*/
{
EFI_STATUS Status;
EFI_HANDLE Handle;
Handle = NULL;
Status = SystemTable->BootServices->InstallProtocolInterface (
&Handle,
&gEfiCpuIoProtocolGuid,
EFI_NATIVE_INTERFACE,
&mCpuIo
);
ASSERT_EFI_ERROR (Status);
return Status;
}
EFI_STATUS
CpuIoCheckParameter (
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN VOID *Buffer,
IN UINT64 Limit
)
/*++
Routine Description:
Check the validation of parameters for CPU I/O interface functions.
Arguments:
Width - Width of the Memory Access
Address - Address of the Memory access
Count - Count of the number of accesses to perform
Buffer - Pointer to the buffer to read from memory
Buffer - Memory buffer for the I/O operation
Limit - Maximum address supported
Returns:
EFI_INVALID_PARAMETER - Buffer is NULL
EFI_UNSUPPORTED - The address range specified by Width, Address and Count is invalid
EFI_UNSUPPORTED - The memory buffer is not aligned
EFI_SUCCESS - Parameters are OK
--*/
{
UINTN AlignMask;
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Address > Limit) {
return EFI_UNSUPPORTED;
}
//
// For FiFo type, the target address won't increase during the access,
// so treat count as 1
//
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
Count = 1;
}
Width = Width & 0x03;
if (Address - 1 + ((UINTN)1 << Width) * Count > Limit) {
return EFI_UNSUPPORTED;
}
AlignMask = ((UINTN)1 << Width) - 1;
if ((UINTN) Buffer & AlignMask) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}

245
DuetPkg/CpuIoDxe/CpuIo.h Normal file
View File

@ -0,0 +1,245 @@
/*++
Copyright (c) 2004, 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.
Module Name:
CpuIo.h
Abstract:
*.h file for the driver
Note: the EFIAPI on the CpuIo functions is used to glue MASM (assembler) code
into C code. By making the MASM functions EFIAPI it ensures that a standard
C calling convention is assumed by the compiler, reguardless of the compiler
flags.
--*/
#ifndef _CPU_IO_H
#define _CPU_IO_H
#include <PiDxe.h>
#include <Protocol/CpuIo.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#define VOLATILE volatile
typedef union {
UINT8 VOLATILE *buf;
UINT8 VOLATILE *ui8;
UINT16 VOLATILE *ui16;
UINT32 VOLATILE *ui32;
UINT64 VOLATILE *ui64;
UINTN VOLATILE ui;
} PTR;
EFI_STATUS
EFIAPI
CpuIoInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
CpuIo driver entry point.
Arguments:
ImageHandle - The firmware allocated handle for the EFI image.
SystemTable - A pointer to the EFI System Table.
Returns:
EFI_SUCCESS - The driver was initialized.
EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
--*/
;
EFI_STATUS
EFIAPI
CpuMemoryServiceRead (
IN EFI_CPU_IO_PROTOCOL *This,
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
OUT VOID *Buffer
)
/*++
Routine Description:
Perform the memory mapped I/O read service
Arguments:
This - Pointer to an instance of the CPU I/O Protocol
Width - Width of the memory mapped I/O operation
Address - Base address of the memory mapped I/O operation
Count - Count of the number of accesses to perform
Buffer - Pointer to the destination buffer to store the results
Returns:
EFI_SUCCESS - The data was read.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_INVALID_PARAMETER - Buffer is NULL.
EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
EFI_UNSUPPORTED - The address range specified by Address, Width,
and Count is not valid.
--*/
;
EFI_STATUS
EFIAPI
CpuMemoryServiceWrite (
IN EFI_CPU_IO_PROTOCOL *This,
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN VOID *Buffer
)
/*++
Routine Description:
Perform the memory mapped I/O write service
Arguments:
This - Pointer to an instance of the CPU I/O Protocol
Width - Width of the memory mapped I/O operation
Address - Base address of the memory mapped I/O operation
Count - Count of the number of accesses to perform
Buffer - Pointer to the source buffer from which to write data
Returns:
EFI_SUCCESS - The data was written.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_INVALID_PARAMETER - Buffer is NULL.
EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
EFI_UNSUPPORTED - The address range specified by Address, Width,
and Count is not valid.
--*/
;
EFI_STATUS
EFIAPI
CpuIoServiceRead (
IN EFI_CPU_IO_PROTOCOL *This,
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
OUT VOID *UserBuffer
)
/*++
Routine Description:
Perform the port I/O read service
Arguments:
This - Pointer to an instance of the CPU I/O Protocol
Width - Width of the port I/O operation
Address - Base address of the port I/O operation
Count - Count of the number of accesses to perform
Buffer - Pointer to the destination buffer to store the results
Returns:
EFI_SUCCESS - The data was read.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_INVALID_PARAMETER - Buffer is NULL.
EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
EFI_UNSUPPORTED - The address range specified by Address, Width,
and Count is not valid.
--*/
;
EFI_STATUS
EFIAPI
CpuIoServiceWrite (
IN EFI_CPU_IO_PROTOCOL *This,
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN VOID *UserBuffer
)
/*++
Routine Description:
Perform the port I/O write service
Arguments:
This - Pointer to an instance of the CPU I/O Protocol
Width - Width of the port I/O operation
Address - Base address of the port I/O operation
Count - Count of the number of accesses to perform
Buffer - Pointer to the source buffer from which to write data
Returns:
EFI_SUCCESS - The data was written.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_INVALID_PARAMETER - Buffer is NULL.
EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
EFI_UNSUPPORTED - The address range specified by Address, Width,
and Count is not valid.
--*/
;
EFI_STATUS
CpuIoCheckParameter (
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN VOID *Buffer,
IN UINT64 Limit
)
/*++
Routine Description:
Check the validation of parameters for CPU I/O interface functions.
Arguments:
Width - Width of the Memory Access
Address - Address of the Memory access
Count - Count of the number of accesses to perform
Buffer - Pointer to the buffer to read from memory
Buffer - Memory buffer for the I/O operation
Limit - Maximum address supported
Returns:
EFI_INVALID_PARAMETER - Buffer is NULL
EFI_UNSUPPORTED - The address range specified by Width, Address and Count is invalid
EFI_UNSUPPORTED - The memory buffer is not aligned
EFI_SUCCESS - Parameters are OK
--*/
;
#endif

View File

@ -0,0 +1,56 @@
#/*++
#
# Copyright (c) 2004, 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.
#
# Module Name:
#
# CpuIo.inf
#
# Abstract:
#
# Component description file for CpuIo module
#
#--*/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = CpuIo
FILE_GUID = BAE7599F-3C6B-43b7-BDF0-9CE07AA91AA6
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = CpuIoInitialize
[Packages]
DuetPkg/DuetPkg.dec
MdePkg/MdePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
[LibraryClasses]
BaseLib
DebugLib
UefiDriverEntryPoint
IoLib
[Sources.common]
CpuIo.c
CpuIo.h
CpuIoAccess.h
[Sources.IA32]
IA32\CpuIoAccess.asm
[Sources.X64]
X64\CpuIoAccess.asm
[Protocols]
gEfiCpuIoProtocolGuid

View File

@ -0,0 +1,216 @@
/*++
#
# Copyright (c) 2004, 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.
Module Name:
CpuIoAccess.h
Abstract:
--*/
#ifndef _CPU_IO_ACCESS_H
#define _CPU_IO_ACCESS_H
#define IA32API __cdecl
UINT8
IA32API
CpuIoRead8 (
IN UINT16 Port
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Port - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
/*++
Routine Description:
Cpu I/O read port
Arguments:
Port: - Port number to read
Returns:
Return read 8 bit value
--*/
UINT16
IA32API
CpuIoRead16 (
IN UINT16 Port
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Port - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
/*++
Routine Description:
Cpu I/O read port
Arguments:
Port: - Port number to read
Returns:
Return read 16 bit value
--*/
UINT32
IA32API
CpuIoRead32 (
IN UINT16 Port
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Port - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
/*++
Routine Description:
Cpu I/O read port
Arguments:
Port: - Port number to read
Returns:
Return read 32 bit value
--*/
VOID
IA32API
CpuIoWrite8 (
IN UINT16 Port,
IN UINT32 Data
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Port - GC_TODO: add argument description
Data - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
/*++
Routine Description:
Cpu I/O write 8 bit data to port
Arguments:
Port: - Port number to read
Data: - Data to write to the Port
Returns:
None
--*/
VOID
IA32API
CpuIoWrite16 (
IN UINT16 Port,
IN UINT32 Data
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Port - GC_TODO: add argument description
Data - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
/*++
Routine Description:
Cpu I/O write 16 bit data to port
Arguments:
Port: - Port number to read
Data: - Data to write to the Port
Returns:
None
--*/
VOID
IA32API
CpuIoWrite32 (
IN UINT16 Port,
IN UINT32 Data
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Port - GC_TODO: add argument description
Data - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
/*++
Routine Description:
Cpu I/O write 32 bit data to port
Arguments:
Port: - Port number to read
Data: - Data to write to the Port
Returns:
None
--*/
#endif

View File

@ -0,0 +1,120 @@
title CpuIoAccess.asm
;------------------------------------------------------------------------------
;*
;* Copyright (c) 2005, 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.
;*
;* Module Name:
;* CpuIoAccess.asm
;*
;* Abstract:
;* Supports IA32 CPU IO operation
;*
;------------------------------------------------------------------------------
;
;
;------------------------------------------------------------------------------
.686
.MODEL FLAT,C
.CODE
UINT8 TYPEDEF BYTE
UINT16 TYPEDEF WORD
UINT32 TYPEDEF DWORD
UINT64 TYPEDEF QWORD
UINTN TYPEDEF UINT32
;------------------------------------------------------------------------------
; UINT8
; CpuIoRead8 (
; IN UINT16 Port
; )
;------------------------------------------------------------------------------
CpuIoRead8 PROC PUBLIC Port:UINT16
mov dx, Port
in al, dx
ret
CpuIoRead8 ENDP
;------------------------------------------------------------------------------
; UINT16
; CpuIoRead16 (
; IN UINT16 Port
; )
;------------------------------------------------------------------------------
CpuIoRead16 PROC PUBLIC Port:UINT16
mov dx, Port
in ax, dx
ret
CpuIoRead16 ENDP
;------------------------------------------------------------------------------
; UINT32
; CpuIoRead32 (
; IN UINT16 Port
; )
;------------------------------------------------------------------------------
CpuIoRead32 PROC PUBLIC Port:UINT16
mov dx, Port
in eax, dx
ret
CpuIoRead32 ENDP
;------------------------------------------------------------------------------
; VOID
; CpuIoWrite8 (
; IN UINT16 Port,
; IN UINT32 Data
; )
;------------------------------------------------------------------------------
CpuIoWrite8 PROC PUBLIC Port:UINT16, Data:UINT32
mov eax, Data
mov dx, Port
out dx, al
ret
CpuIoWrite8 ENDP
;------------------------------------------------------------------------------
; VOID
; CpuIoWrite16 (
; IN UINT16 Port,
; IN UINT32 Data
; )
;------------------------------------------------------------------------------
CpuIoWrite16 PROC PUBLIC Port:UINT16, Data:UINT32
mov eax, Data
mov dx, Port
out dx, ax
ret
CpuIoWrite16 ENDP
;------------------------------------------------------------------------------
; VOID
; CpuIoWrite32 (
; IN UINT16 Port,
; IN UINT32 Data
; )
;------------------------------------------------------------------------------
CpuIoWrite32 PROC PUBLIC Port:UINT16, Data:UINT32
mov eax, Data
mov dx, Port
out dx, eax
ret
CpuIoWrite32 ENDP
END

View File

@ -0,0 +1,26 @@
/*++
Copyright (c) 2004, 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.
Module Name:
Ia32CpuIo.dxs
Abstract:
Dependency expression source file.
--*/
#include "EfiDepex.h"
DEPENDENCY_START
TRUE
DEPENDENCY_END

View File

@ -0,0 +1,111 @@
title CpuIoAccess.asm
;------------------------------------------------------------------------------
;*
;* Copyright (c) 2005 - 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.
;*
;* Module Name:
;* CpuIoAccess.asm
;*
;* Abstract:
;* Supports x64 CPU IO operation
;*
;------------------------------------------------------------------------------
;
;
;
; Abstract:
;
;
;------------------------------------------------------------------------------
.CODE
;------------------------------------------------------------------------------
; UINT8
; CpuIoRead8 (
; UINT16 Port // rcx
; )
;------------------------------------------------------------------------------
CpuIoRead8 PROC PUBLIC
xor eax, eax
mov dx, cx
in al, dx
ret
CpuIoRead8 ENDP
;------------------------------------------------------------------------------
; VOID
; CpuIoWrite8 (
; UINT16 Port, // rcx
; UINT32 Data // rdx
; )
;------------------------------------------------------------------------------
CpuIoWrite8 PROC PUBLIC
mov eax, edx
mov dx, cx
out dx, al
ret
CpuIoWrite8 ENDP
;------------------------------------------------------------------------------
; UINT16
; CpuIoRead16 (
; UINT16 Port // rcx
; )
;------------------------------------------------------------------------------
CpuIoRead16 PROC PUBLIC
xor eax, eax
mov dx, cx
in ax, dx
ret
CpuIoRead16 ENDP
;------------------------------------------------------------------------------
; VOID
; CpuIoWrite16 (
; UINT16 Port, // rcx
; UINT32 Data // rdx
; )
;------------------------------------------------------------------------------
CpuIoWrite16 PROC PUBLIC
mov eax, edx
mov dx, cx
out dx, ax
ret
CpuIoWrite16 ENDP
;------------------------------------------------------------------------------
; UINT32
; CpuIoRead32 (
; UINT16 Port // rcx
; )
;------------------------------------------------------------------------------
CpuIoRead32 PROC PUBLIC
mov dx, cx
in eax, dx
ret
CpuIoRead32 ENDP
;------------------------------------------------------------------------------
; VOID
; CpuIoWrite32 (
; UINT16 Port, // rcx
; UINT32 Data // rdx
; )
;------------------------------------------------------------------------------
CpuIoWrite32 PROC PUBLIC
mov eax, edx
mov dx, cx
out dx, eax
ret
CpuIoWrite32 ENDP
END

View File

@ -9,4 +9,8 @@
[Guids.common]
gEfiPciExpressBaseAddressGuid = {0x3677d529, 0x326f, 0x4603, {0xa9, 0x26, 0xea, 0xac, 0xe0, 0x1d, 0xcb, 0xb0 }}
gEfiAcpiDescriptionGuid = {0x3c699197, 0x093c, 0x4c69, {0xb0, 0x6b, 0x12, 0x8a, 0xe3, 0x48, 0x1d, 0xc9 }}
gEfiAcpiDescriptionGuid = {0x3c699197, 0x093c, 0x4c69, {0xb0, 0x6b, 0x12, 0x8a, 0xe3, 0x48, 0x1d, 0xc9 }}
gEfiFlashMapHobGuid = { 0xb091e7d2, 0x5a0, 0x4198, {0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 }}
[Protocols.common]
gEfiLegacyBiosThunkProtocolGuid = {0x4c51a7ba, 0x7195, 0x442d, {0x87, 0x92, 0xbe, 0xea, 0x6e, 0x2f, 0xf6, 0xec}}

View File

@ -9,7 +9,7 @@
SUPPORTED_ARCHITECTURES = IA32|X64
BUILD_TARGETS = DEBUG
SKUID_IDENTIFIER = DEFAULT
#FLASH_DEFINITION = DuetPkg/DuetPkg.fdf
FLASH_DEFINITION = DuetPkg/DuetPkg.fdf
[LibraryClasses.common]
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
@ -26,15 +26,106 @@
HiiLib|MdePkg/Library/HiiLib/HiiLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
BaseUefiTianoDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf
ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
PlatformBdsLib|DuetPkg/Library/DuetBdsLib/PlatformBds.inf
IfrSupportLib|MdePkg/Library/IfrSupportLib/IfrSupportLib.inf
ExtendedIfrSupportLib|MdeModulePkg/Library/ExtendedIfrSupportLib/ExtendedIfrSupportLib.inf
GenericBdsLib|MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
GraphicsLib|MdeModulePkg/Library/GraphicsLib/GraphicsLib.inf
ExtendedHiiLib|MdeModulePkg/Library/ExtendedHiiLib/ExtendedHiiLib.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
DxePiLib|MdePkg/Library/DxePiLib/DxePiLib.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
OemHookStatusCodeLib|IntelFrameworkModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
[LibraryClasses.common.DXE_DRIVER]
MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
SerialPortLib|MdePkg/Library/SerialPortLibNull/SerialPortLibNull.inf
MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
IoLib|IntelFrameworkPkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.inf
UsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
[Components.IA32]
[LibraryClasses.common.DXE_CORE]
HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
[LibraryClasses.common.DXE_RUNTIME_DRIVER]
MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
SerialPortLib|MdePkg/Library/SerialPortLibNull/SerialPortLibNull.inf
IoLib|IntelFrameworkPkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.inf
TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf
[LibraryClasses.common.UEFI_DRIVER]
MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
[LibraryClasses.common.UEFI_APPLICATION]
MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
[Components.common]
DuetPkg/DxeIpl/DxeIpl.inf
MdeModulePkg/Core/Dxe/DxeMain.inf
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
DuetPkg/FSVariable/FSVariable.inf
MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
IntelFrameworkModulePkg/Universal/StatusCode/Dxe/DxeStatusCode.inf
MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf
MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
DuetPkg/DataHubGenDxe/DataHubGen.inf
DuetPkg/FvbRuntimeService/DUETFwh.inf
DuetPkg/EfiLdr/EfiLdr.inf
MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
DuetPkg/CpuIoDxe/CpuIo.inf
DuetPkg/CpuDxe/Cpu.inf
IntelFrameworkModulePkg/Universal/Legacy8259Dxe/8259.inf
DuetPkg/KbcResetDxe/Reset.inf
DuetPkg/LegacyMetronome/Metronome.inf
[Components.X64]
DuetPkg/DxeIpl/DxeIpl.inf
DuetPkg/DataHubGenDxe/DataHubGen.inf
DuetPkg/PcRtc/RealTimeClock.inf
DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf
# IDE Support
#IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf
# Usb Support
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf
# ISA Support
DuetPkg/IsaAcpiDxe/IsaAcpi.inf
DuetPkg/BootSector/BootSector.inf

189
DuetPkg/DuetPkg.fdf Normal file
View File

@ -0,0 +1,189 @@
# This is NT32 FDF file with UEFI HII features enabled
#
# Copyright (c) 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.
#
################################################################################
#
# FD Section
# The [FD] Section is made up of the definition statements and a
# description of what goes into the Flash Device Image. Each FD section
# defines one flash "device" image. A flash device image may be one of
# the following: Removable media bootable image (like a boot floppy
# image,) an Option ROM image (that would be "flashed" into an add-in
# card,) a System "Flash" image (that would be burned into a system's
# flash) or an Update ("Capsule") image that will be used to update and
# existing system flash.
#
################################################################################
[FD.DuetMainFd]
BaseAddress = 0x0 #The base address of the FLASH Device.
Size = 0x002a0000 #The size in bytes of the FLASH Device
ErasePolarity = 1
BlockSize = 0x10000
NumBlocks = 0x2a
0x00000000|0x002a0000
################################################################################
#
# FV Section
#
# [FV] section is used to define what components or modules are placed within a flash
# device file. This section also defines order the components and modules are positioned
# within the image. The [FV] section consists of define statements, set statements and
# module statements.
#
################################################################################
[FV.DuetEfiMainFv]
FvAlignment = 16 #FV alignment and FV attributes setting.
ERASE_POLARITY = 1
MEMORY_MAPPED = TRUE
STICKY_WRITE = TRUE
LOCK_CAP = TRUE
LOCK_STATUS = TRUE
WRITE_DISABLED_CAP = TRUE
WRITE_ENABLED_CAP = TRUE
WRITE_STATUS = TRUE
WRITE_LOCK_CAP = TRUE
WRITE_LOCK_STATUS = TRUE
READ_DISABLED_CAP = TRUE
READ_ENABLED_CAP = TRUE
READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
INF DuetPkg/FSVariable/FSVariable.inf
INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
INF IntelFrameworkModulePkg/Universal/StatusCode/Dxe/DxeStatusCode.inf
INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
INF IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf
INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
INF DuetPkg/DataHubGenDxe/DataHubGen.inf
INF DuetPkg/FvbRuntimeService/DUETFwh.inf
INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
INF DuetPkg/CpuIoDxe/CpuIo.inf
INF DuetPkg/CpuDxe/Cpu.inf
INF IntelFrameworkModulePkg/Universal/Legacy8259Dxe/8259.inf
INF DuetPkg/KbcResetDxe/Reset.inf
INF DuetPkg/LegacyMetronome/Metronome.inf
INF DuetPkg/PcRtc/RealTimeClock.inf
INF DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
INF IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf
# IDE Support
#IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf
# Usb Support
INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
INF MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf
# ISA Support
INF DuetPkg/IsaAcpiDxe/IsaAcpi.inf
[Rule.Common.PEI_CORE]
FILE PEI_CORE = $(NAMED_GUID) {
PE32 PE32 |.efi
UI STRING ="$(MODULE_NAME)" Optional
VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
}
[Rule.Common.PEIM]
FILE PEIM = $(NAMED_GUID) {
PEI_DEPEX PEI_DEPEX Optional |.depex
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
}
[Rule.Common.PEIM.TIANOCOMPRESSED]
FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 {
PEI_DEPEX PEI_DEPEX Optional |.depex
GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
}
}
[Rule.Common.DXE_CORE]
FILE DXE_CORE = $(NAMED_GUID) {
COMPRESS PI_STD {
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
}
}
[Rule.Common.UEFI_DRIVER]
FILE DRIVER = $(NAMED_GUID) {
DXE_DEPEX DXE_DEPEX Optional |.depex
COMPRESS PI_STD {
GUIDED {
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
}
}
}
[Rule.Common.DXE_DRIVER]
FILE DRIVER = $(NAMED_GUID) {
DXE_DEPEX DXE_DEPEX Optional |.depex
COMPRESS PI_STD {
GUIDED {
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
}
}
}
[Rule.Common.DXE_RUNTIME_DRIVER]
FILE DRIVER = $(NAMED_GUID) {
DXE_DEPEX DXE_DEPEX Optional |.depex
COMPRESS PI_STD {
GUIDED {
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
}
}
}
[Rule.Common.UEFI_APPLICATION]
FILE APPLICATION = $(NAMED_GUID) {
COMPRESS PI_STD {
GUIDED {
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
}
}
}

View File

@ -20,7 +20,7 @@
INF_VERSION = 0x00010005
BASE_NAME = DxeIpl
FILE_GUID = 2119BBD7-9432-4f47-B5E2-5C4EA31B6BDC
MODULE_TYPE = USER_DEFINED
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
@ -38,6 +38,7 @@
BaseMemoryLib
PrintLib
ReportStatusCodeLib
UefiDriverEntryPoint
[Sources.common]
DxeIpl.h
@ -65,9 +66,9 @@
Ia32\Paging.c
Ia32\VirtualMemory.h
[BuildOptions.common]
#[BuildOptions.common]
#MSFT:*_*_IA32_DLINK_FLAGS = /out:"$(BIN_DIR)\SecMain.exe" /base:0x10000000 /pdb:"$(BIN_DIR)\SecMain.pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib
MSFT:*_*_IA32_CC_FLAGS = /nologo /W4 /WX /Gy /c /D UNICODE /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
MSFT:*_*_IA32_PP_FLAGS = /nologo /E /TC /FI$(DEST_DIR_DEBUG)/AutoGen.h
MSFT:*_*_IA32_ASM_FLAGS = /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi
MSFT:*_*_IA32_ASMLINK_FLAGS = /link /nologo /tiny
#MSFT:*_*_IA32_CC_FLAGS = /nologo /W4 /WX /Gy /c /D UNICODE /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
#MSFT:*_*_IA32_PP_FLAGS = /nologo /E /TC /FI$(DEST_DIR_DEBUG)/AutoGen.h
#MSFT:*_*_IA32_ASM_FLAGS = /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi
#MSFT:*_*_IA32_ASMLINK_FLAGS = /link /nologo /tiny

View File

@ -22,7 +22,6 @@ Abstract:
#ifndef _EFI_FLASHMAP_H_
#define _EFI_FLASHMAP_H_
//
// Definition for flash map GUIDed HOBs
//
@ -59,6 +58,7 @@ typedef UINT8 EFI_FLASH_AREA_TYPE;
// An individual sub-area Entry.
// A single flash area may consist of more than one sub-area.
//
/**
typedef struct {
EFI_FLASH_AREA_ATTRIBUTES Attributes;
UINT32 Reserved;
@ -121,6 +121,32 @@ typedef struct {
UINT8 Reserved[3];
EFI_GUID AreaTypeGuid;
} EFI_FLASH_AREA_DATA;
**/
typedef struct {
EFI_FLASH_AREA_ATTRIBUTES Attributes;
UINT32 Reserved;
EFI_PHYSICAL_ADDRESS Base;
EFI_PHYSICAL_ADDRESS Length;
EFI_GUID FileSystem;
} EFI_FLASH_SUBAREA_ENTRY;
typedef struct {
UINT8 Reserved[3];
EFI_FLASH_AREA_TYPE AreaType;
EFI_GUID AreaTypeGuid;
UINT32 NumberOfEntries;
EFI_FLASH_SUBAREA_ENTRY Entries[1];
//
// Extended Hob data.
//
// VolumeId and FilePath indicating a unique file.
//
UINT32 VolumeId;
CHAR16 FilePath[256];
UINT32 ActuralSize;
UINT32 Offset;
} EFI_FLASH_MAP_FS_ENTRY_DATA;
#pragma pack()

View File

@ -0,0 +1,170 @@
/*++
Copyright (c) 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.
Module Name:
ComponentName.c
Abstract:
--*/
#include "PcatIsaAcpi.h"
//
// EFI Component Name Functions
//
EFI_STATUS
EFIAPI
PcatIsaAcpiComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
PcatIsaAcpiComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI Component Name Protocol
//
EFI_COMPONENT_NAME2_PROTOCOL gPcatIsaAcpiComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PcatIsaAcpiComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PcatIsaAcpiComponentNameGetControllerName,
"en"
};
EFI_COMPONENT_NAME_PROTOCOL gPcatIsaAcpiComponentName = {
PcatIsaAcpiComponentNameGetDriverName,
PcatIsaAcpiComponentNameGetControllerName,
"eng"
};
static EFI_UNICODE_STRING_TABLE mPcatIsaAcpiDriverNameTable[] = {
{
"eng;en",
L"PC-AT ISA Device Enumeration Driver"
},
{
NULL,
NULL
}
};
EFI_STATUS
EFIAPI
PcatIsaAcpiComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
Language - A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that that the caller
is requesting, and it must match one of the languages specified
in SupportedLanguages. The number of languages supported by a
driver is up to the driver writer.
DriverName - A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
Returns:
EFI_SUCCES - The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - DriverName is NULL.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mPcatIsaAcpiDriverNameTable,
DriverName,
(BOOLEAN)(This == &gPcatIsaAcpiComponentName)
);
}
EFI_STATUS
EFIAPI
PcatIsaAcpiComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
ControllerHandle - The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
ChildHandle - The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
Language - A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that that the caller is requesting, and it must match one
of the languages specified in SupportedLanguages. The
number of languages supported by a driver is up to the
driver writer.
ControllerName - A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language specified
by Language from the point of view of the driver specified
by This.
Returns:
EFI_SUCCESS - The Unicode string for the user readable name in the
language specified by Language for the driver
specified by This was returned in DriverName.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - ControllerName is NULL.
EFI_UNSUPPORTED - The driver specified by This is not currently managing
the controller specified by ControllerHandle and
ChildHandle.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return EFI_UNSUPPORTED;
}

View File

@ -0,0 +1,306 @@
/*++
Copyright (c) 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.
Module Name:
IsaAcpi.c
Abstract:
ISA ACPI Protocol Implementation
Revision History
--*/
#include "PcatIsaAcpi.h"
//
// Platform specific data for the ISA devices that are present.in the platform
//
//
// COM 1 UART Controller
//
static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiCom1DeviceResources[] = {
{EfiIsaAcpiResourceIo, 0, 0x3f8, 0x3ff},
{EfiIsaAcpiResourceInterrupt, 0, 4, 0},
{EfiIsaAcpiResourceEndOfList, 0, 0, 0}
};
//
// COM 2 UART Controller
//
static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiCom2DeviceResources[] = {
{EfiIsaAcpiResourceIo, 0, 0x2f8, 0x2ff},
{EfiIsaAcpiResourceInterrupt, 0, 3, 0},
{EfiIsaAcpiResourceEndOfList, 0, 0, 0}
};
//
// PS/2 Keyboard Controller
//
static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiPs2KeyboardDeviceResources[] = {
{EfiIsaAcpiResourceIo, 0, 0x60, 0x64},
{EfiIsaAcpiResourceInterrupt, 0, 1, 0},
{EfiIsaAcpiResourceEndOfList, 0, 0, 0}
};
//
// PS/2 Mouse Controller
//
static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiPs2MouseDeviceResources[] = {
{EfiIsaAcpiResourceIo, 0, 0x60, 0x64},
{EfiIsaAcpiResourceInterrupt, 0, 12, 0},
{EfiIsaAcpiResourceEndOfList, 0, 0, 0}
};
//
// Floppy Disk Controller
//
static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiFloppyResources[] = {
{EfiIsaAcpiResourceIo, 0, 0x3f0, 0x3f7},
{EfiIsaAcpiResourceInterrupt, 0, 6, 0},
{EfiIsaAcpiResourceDma, EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE | EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8 | EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE, 2, 0},
{EfiIsaAcpiResourceEndOfList, 0, 0, 0}
};
//
// Table of ISA Controllers
//
EFI_ISA_ACPI_RESOURCE_LIST gPcatIsaAcpiDeviceList[] = {
{{EISA_PNP_ID(0x501), 0}, mPcatIsaAcpiCom1DeviceResources }, // COM 1 UART Controller
{{EISA_PNP_ID(0x501), 1}, mPcatIsaAcpiCom2DeviceResources }, // COM 2 UART Controller
{{EISA_PNP_ID(0x303), 0}, mPcatIsaAcpiPs2KeyboardDeviceResources }, // PS/2 Keyboard Controller
{{EISA_PNP_ID(0x303), 1}, mPcatIsaAcpiPs2MouseDeviceResources }, // PS/2 Mouse Controller
{{EISA_PNP_ID(0x604), 0}, mPcatIsaAcpiFloppyResources }, // Floppy Disk Controller A:
{{EISA_PNP_ID(0x604), 1}, mPcatIsaAcpiFloppyResources }, // Floppy Disk Controller B:
{{0, 0}, NULL } // End if ISA Controllers
};
//
// ISA ACPI Protocol Functions
//
VOID
IsaDeviceLookup (
IN EFI_ISA_ACPI_DEVICE_ID *Device,
OUT EFI_ISA_ACPI_RESOURCE_LIST **IsaAcpiDevice,
OUT EFI_ISA_ACPI_RESOURCE_LIST **NextIsaAcpiDevice
)
/*++
Routine Description:
Enumerate the ISA devices on the ISA bus
Arguments:
Returns:
--*/
{
UINTN Index;
*IsaAcpiDevice = NULL;
if (NextIsaAcpiDevice != NULL) {
*NextIsaAcpiDevice = NULL;
}
if (Device == NULL) {
Index = 0;
} else {
for(Index = 0; gPcatIsaAcpiDeviceList[Index].ResourceItem != NULL; Index++) {
if (Device->HID == gPcatIsaAcpiDeviceList[Index].Device.HID &&
Device->UID == gPcatIsaAcpiDeviceList[Index].Device.UID ) {
break;
}
}
if (gPcatIsaAcpiDeviceList[Index].ResourceItem == NULL) {
return;
}
*IsaAcpiDevice = &(gPcatIsaAcpiDeviceList[Index]);
Index++;
}
if (gPcatIsaAcpiDeviceList[Index].ResourceItem != NULL && NextIsaAcpiDevice != NULL) {
*NextIsaAcpiDevice = &(gPcatIsaAcpiDeviceList[Index]);
}
}
EFI_STATUS
EFIAPI
IsaDeviceEnumerate (
IN EFI_ISA_ACPI_PROTOCOL *This,
OUT EFI_ISA_ACPI_DEVICE_ID **Device
)
/*++
Routine Description:
Enumerate the ISA devices on the ISA bus
Arguments:
Returns:
--*/
{
EFI_ISA_ACPI_RESOURCE_LIST *IsaAcpiDevice;
EFI_ISA_ACPI_RESOURCE_LIST *NextIsaAcpiDevice;
IsaDeviceLookup (*Device, &IsaAcpiDevice, &NextIsaAcpiDevice);
if (NextIsaAcpiDevice == NULL) {
return EFI_NOT_FOUND;
}
*Device = &(NextIsaAcpiDevice->Device);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
IsaDeviceSetPower (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device,
IN BOOLEAN OnOff
)
/*++
Routine Description:
Set ISA device power
Arguments:
Returns:
--*/
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
IsaGetCurrentResource (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device,
OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList
)
/*++
Routine Description:
Get current Resource of the specific ISA device
Arguments:
Returns:
--*/
{
IsaDeviceLookup (Device, ResourceList, NULL);
if (*ResourceList == NULL) {
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
IsaGetPossibleResource (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device,
OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
IsaSetResource (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device,
IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
IsaEnableDevice (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device,
IN BOOLEAN Enable
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
IsaInitDevice (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
IsaInterfaceInit (
IN EFI_ISA_ACPI_PROTOCOL *This
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
return EFI_SUCCESS;
}

View File

@ -0,0 +1,50 @@
#/*++
#
# Copyright (c) 2005, 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.
#
# Module Name:
# IsaAcpi.inf
#
# Abstract:
# Component description file for PCAT ISA ACPI driver
#
#--*/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = IsaAcpi
FILE_GUID = 38A0EC22-FBE7-4911-8BC1-176E0D6C1DBD
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x0002000A
ENTRY_POINT = PcatIsaAcpiDriverEntryPoint
[Packages]
MdePkg/MdePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
DuetPkg/DuetPkg.dec
[LibraryClasses]
UefiDriverEntryPoint
UefiBootServicesTableLib
UefiLib
[Sources]
PcatIsaAcpi.h
PcatIsaAcpi.c
IsaAcpi.c
ComponentName.c
[Protocols]
gEfiPciIoProtocolGuid
gEfiIsaAcpiProtocolGuid

View File

@ -0,0 +1,329 @@
/*++
Copyright (c) 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.
Module Name:
PcatIsaAcpi.c
Abstract:
EFI PCAT ISA ACPI Driver for a Generic PC Platform
Revision History
--*/
#include "PcatIsaAcpi.h"
//
// PcatIsaAcpi Driver Binding Protocol
//
EFI_DRIVER_BINDING_PROTOCOL gPcatIsaAcpiDriverBinding = {
PcatIsaAcpiDriverBindingSupported,
PcatIsaAcpiDriverBindingStart,
PcatIsaAcpiDriverBindingStop,
0xa,
NULL,
NULL
};
EFI_STATUS
EFIAPI
PcatIsaAcpiDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
the entry point of the PcatIsaAcpi driver
Arguments:
Returns:
--*/
{
return EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gPcatIsaAcpiDriverBinding,
ImageHandle,
&gPcatIsaAcpiComponentName,
&gPcatIsaAcpiComponentName2
);
}
EFI_STATUS
EFIAPI
PcatIsaAcpiDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
ControllerDriver Protocol Method
Arguments:
Returns:
--*/
{
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
PCI_TYPE00 Pci;
//
// Get PciIo protocol instance
//
Status = gBS->OpenProtocol (
Controller,
&gEfiPciIoProtocolGuid,
&PciIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR(Status)) {
return Status;
}
Status = PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint32,
0,
sizeof(Pci) / sizeof(UINT32),
&Pci);
if (!EFI_ERROR (Status)) {
Status = EFI_UNSUPPORTED;
if ((Pci.Hdr.Command & 0x03) == 0x03) {
if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
//
// See if this is a standard PCI to ISA Bridge from the Base Code and Class Code
//
if (Pci.Hdr.ClassCode[1] == PCI_CLASS_ISA) {
Status = EFI_SUCCESS;
}
//
// See if this is an Intel PCI to ISA bridge in Positive Decode Mode
//
if (Pci.Hdr.ClassCode[1] == PCI_CLASS_ISA_POSITIVE_DECODE &&
Pci.Hdr.VendorId == 0x8086 &&
Pci.Hdr.DeviceId == 0x7110) {
Status = EFI_SUCCESS;
}
}
}
}
gBS->CloseProtocol (
Controller,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
return Status;
}
EFI_STATUS
EFIAPI
PcatIsaAcpiDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Install EFI_ISA_ACPI_PROTOCOL
Arguments:
Returns:
--*/
{
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
PCAT_ISA_ACPI_DEV *PcatIsaAcpiDev;
PcatIsaAcpiDev = NULL;
//
// Open the PCI I/O Protocol Interface
//
PciIo = NULL;
Status = gBS->OpenProtocol (
Controller,
&gEfiPciIoProtocolGuid,
&PciIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto Done;
}
Status = PciIo->Attributes (
PciIo,
EfiPciIoAttributeOperationEnable,
EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,
NULL
);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Allocate memory for the PCAT ISA ACPI Device structure
//
PcatIsaAcpiDev = NULL;
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof(PCAT_ISA_ACPI_DEV),
&PcatIsaAcpiDev
);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Initialize the PCAT ISA ACPI Device structure
//
PcatIsaAcpiDev->Signature = PCAT_ISA_ACPI_DEV_SIGNATURE;
PcatIsaAcpiDev->Handle = Controller;
PcatIsaAcpiDev->PciIo = PciIo;
//
// IsaAcpi interface
//
(PcatIsaAcpiDev->IsaAcpi).DeviceEnumerate = IsaDeviceEnumerate;
(PcatIsaAcpiDev->IsaAcpi).SetPower = IsaDeviceSetPower;
(PcatIsaAcpiDev->IsaAcpi).GetCurResource = IsaGetCurrentResource;
(PcatIsaAcpiDev->IsaAcpi).GetPosResource = IsaGetPossibleResource;
(PcatIsaAcpiDev->IsaAcpi).SetResource = IsaSetResource;
(PcatIsaAcpiDev->IsaAcpi).EnableDevice = IsaEnableDevice;
(PcatIsaAcpiDev->IsaAcpi).InitDevice = IsaInitDevice;
(PcatIsaAcpiDev->IsaAcpi).InterfaceInit = IsaInterfaceInit;
//
// Install the ISA ACPI Protocol interface
//
Status = gBS->InstallMultipleProtocolInterfaces (
&Controller,
&gEfiIsaAcpiProtocolGuid, &PcatIsaAcpiDev->IsaAcpi,
NULL
);
Done:
if (EFI_ERROR (Status)) {
if (PciIo) {
PciIo->Attributes (
PciIo,
EfiPciIoAttributeOperationDisable,
EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,
NULL
);
}
gBS->CloseProtocol (
Controller,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
if (PcatIsaAcpiDev != NULL) {
gBS->FreePool (PcatIsaAcpiDev);
}
return Status;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
PcatIsaAcpiDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
EFI_STATUS Status;
EFI_ISA_ACPI_PROTOCOL *IsaAcpi;
PCAT_ISA_ACPI_DEV *PcatIsaAcpiDev;
//
// Get the ISA ACPI Protocol Interface
//
Status = gBS->OpenProtocol (
Controller,
&gEfiIsaAcpiProtocolGuid,
&IsaAcpi,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the PCAT ISA ACPI Device structure from the ISA ACPI Protocol
//
PcatIsaAcpiDev = PCAT_ISA_ACPI_DEV_FROM_THIS (IsaAcpi);
PcatIsaAcpiDev->PciIo->Attributes (
PcatIsaAcpiDev->PciIo,
EfiPciIoAttributeOperationDisable,
EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,
NULL
);
//
// Uninstall protocol interface: EFI_ISA_ACPI_PROTOCOL
//
Status = gBS->UninstallProtocolInterface (
Controller,
&gEfiIsaAcpiProtocolGuid, &PcatIsaAcpiDev->IsaAcpi
);
if (EFI_ERROR (Status)) {
return Status;
}
gBS->CloseProtocol (
Controller,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
gBS->FreePool (PcatIsaAcpiDev);
return EFI_SUCCESS;
}

View File

@ -0,0 +1,159 @@
/*++
Copyright (c) 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.
Module Name:
PcatIsaAcpi.h
Abstract:
EFI PCAT ISA ACPI Driver for a Generic PC Platform
Revision History
--*/
#ifndef _PCAT_ISA_ACPI_H_
#define _PCAT_ISA_ACPI_H_
#include <PiDxe.h>
#include <IndustryStandard/Pci.h>
#include <Protocol/DevicePath.h>
#include <Protocol/PciIo.h>
#include <Protocol/IsaIo.h>
#include <Protocol/DriverBinding.h>
#include <Protocol/ComponentName.h>
#include <Protocol/ComponentName2.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/IsaAcpi.h>
//
// PCAT ISA ACPI device private data structure
//
#define PCAT_ISA_ACPI_DEV_SIGNATURE EFI_SIGNATURE_32('L','P','C','D')
typedef struct {
UINTN Signature;
EFI_HANDLE Handle;
EFI_ISA_ACPI_PROTOCOL IsaAcpi;
EFI_PCI_IO_PROTOCOL *PciIo;
} PCAT_ISA_ACPI_DEV;
#define PCAT_ISA_ACPI_DEV_FROM_THIS(a) _CR(a, PCAT_ISA_ACPI_DEV, IsaAcpi)
//
// Global Variables
//
extern EFI_DRIVER_BINDING_PROTOCOL gPcatIsaAcpiDriverBinding;
extern EFI_COMPONENT_NAME2_PROTOCOL gPcatIsaAcpiComponentName2;
extern EFI_COMPONENT_NAME_PROTOCOL gPcatIsaAcpiComponentName;
//
// Prototypes for Driver model protocol interface
//
EFI_STATUS
EFIAPI
PcatIsaAcpiDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
PcatIsaAcpiDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
PcatIsaAcpiDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
//
// Prototypes for the ISA ACPI protocol interface
//
EFI_STATUS
EFIAPI
IsaDeviceEnumerate (
IN EFI_ISA_ACPI_PROTOCOL *This,
OUT EFI_ISA_ACPI_DEVICE_ID **Device
);
EFI_STATUS
EFIAPI
IsaDeviceSetPower (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device,
IN BOOLEAN OnOff
);
EFI_STATUS
EFIAPI
IsaGetCurrentResource (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device,
OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList
);
EFI_STATUS
EFIAPI
IsaGetPossibleResource (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device,
OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList
);
EFI_STATUS
EFIAPI
IsaSetResource (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device,
IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList
);
EFI_STATUS
EFIAPI
IsaEnableDevice (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device,
IN BOOLEAN Enable
);
EFI_STATUS
EFIAPI
IsaInitDevice (
IN EFI_ISA_ACPI_PROTOCOL *This,
IN EFI_ISA_ACPI_DEVICE_ID *Device
);
EFI_STATUS
EFIAPI
IsaInterfaceInit (
IN EFI_ISA_ACPI_PROTOCOL *This
);
#endif

View File

@ -0,0 +1,79 @@
/*++
Copyright (c) 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.
Module Name:
Ia32Reset.c
Abstract:
--*/
#include "Reset.h"
//
// The handle onto which the Reset Architectural Protocol is installed
//
EFI_HANDLE mResetHandle = NULL;
EFI_STATUS
EFIAPI
InitializeReset (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Initialize the state information for the Reset Architectural Protocol
Arguments:
ImageHandle of the loaded driver
Pointer to the System Table
Returns:
Status
EFI_SUCCESS - thread can be successfully created
EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
EFI_DEVICE_ERROR - cannot create the timer service
--*/
// TODO: SystemTable - add argument and description to function comment
{
EFI_STATUS Status;
//
// Make sure the Reset Architectural Protocol is not already installed in the system
//
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiResetArchProtocolGuid);
//
// Hook the runtime service table
//
SystemTable->RuntimeServices->ResetSystem = KbcResetSystem;
//
// Now install the Reset RT AP on a new handle
//
Status = gBS->InstallMultipleProtocolInterfaces (
&mResetHandle,
&gEfiResetArchProtocolGuid,
NULL,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@ -0,0 +1,27 @@
/*++
Copyright (c) 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.
Module Name:
Ia32Reset.dxs
Abstract:
Dependency expression source file.
--*/
#include "EfiDepex.h"
#include EFI_PROTOCOL_DEFINITION (CpuIO)
DEPENDENCY_START
EFI_CPU_IO_PROTOCOL_GUID
DEPENDENCY_END

View File

@ -0,0 +1,117 @@
/*++
Copyright (c) 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.
Module Name:
IpfReset.c
Abstract:
--*/
#include "Cf9Reset.h"
SAL_RETURN_REGS
ResetEsalServicesClassCommonEntry (
IN UINT64 FunctionId,
IN UINT64 Arg2,
IN UINT64 Arg3,
IN UINT64 Arg4,
IN UINT64 Arg5,
IN UINT64 Arg6,
IN UINT64 Arg7,
IN UINT64 Arg8,
IN SAL_EXTENDED_SAL_PROC ExtendedSalProc,
IN BOOLEAN VirtualMode,
IN VOID *Global
)
/*++
Routine Description:
Main entry for Extended SAL Reset Services
Arguments:
FunctionId Function Id which needed to be called.
Arg2 EFI_RESET_TYPE, whether WARM of COLD reset
Arg3 Last EFI_STATUS
Arg4 Data Size of UNICODE STRING passed in ARG5
Arg5 Unicode String which CHAR16*
Returns:
SAL_RETURN_REGS
--*/
// TODO: Arg6 - add argument and description to function comment
// TODO: Arg7 - add argument and description to function comment
// TODO: Arg8 - add argument and description to function comment
// TODO: ExtendedSalProc - add argument and description to function comment
// TODO: VirtualMode - add argument and description to function comment
// TODO: Global - add argument and description to function comment
{
SAL_RETURN_REGS ReturnVal;
switch (FunctionId) {
case ResetSystem:
KbcResetSystem (Arg2, Arg3, (UINTN) Arg4, (VOID *) Arg5);
ReturnVal.Status = EFI_SUCCESS;
break;
default:
ReturnVal.Status = EFI_SAL_INVALID_ARGUMENT;
break;
}
return ReturnVal;
}
EFI_STATUS
EFIAPI
InitializeReset (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Initialize the state information for the Reset Architectural Protocol
Arguments:
ImageHandle of the loaded driver
Pointer to the System Table
Returns:
Status
EFI_SUCCESS - thread can be successfully created
EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
EFI_DEVICE_ERROR - cannot create the timer service
--*/
// TODO: SystemTable - add argument and description to function comment
{
EfiInitializeRuntimeDriverLib (ImageHandle, SystemTable, NULL);
RegisterEsalClass (
&gEfiExtendedSalResetServicesProtocolGuid,
NULL,
ResetEsalServicesClassCommonEntry,
ResetSystem,
NULL
);
return EFI_SUCCESS;
}

View File

@ -0,0 +1,27 @@
/*++
Copyright (c) 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.
Module Name:
IpfReset.dxs
Abstract:
Dependency expression source file.
--*/
#include "EfiDepex.h"
#include EFI_PROTOCOL_DEFINITION (ExtendedSalGuid)
DEPENDENCY_START
EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID
DEPENDENCY_END

View File

@ -0,0 +1,70 @@
/*++
Copyright (c) 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.
Module Name:
Reset.c
Abstract:
Reset Architectural Protocol implementation
--*/
#include "Reset.h"
VOID
EFIAPI
KbcResetSystem (
IN EFI_RESET_TYPE ResetType,
IN EFI_STATUS ResetStatus,
IN UINTN DataSize,
IN CHAR16 *ResetData OPTIONAL
)
/*++
Routine Description:
Reset the system.
Arguments:
ResetType - warm or cold
ResetStatus - possible cause of reset
DataSize - Size of ResetData in bytes
ResetData - Optional Unicode string
For details, see efiapi.h
Returns:
Does not return if the reset takes place.
EFI_INVALID_PARAMETER If ResetType is invalid.
--*/
{
UINT8 Data;
switch (ResetType) {
case EfiResetWarm:
case EfiResetCold:
case EfiResetShutdown:
Data = 0xfe;
IoWrite8 (0x64, Data);
break;
default:
return ;
}
//
// Given we should have reset getting here would be bad
//
ASSERT (FALSE);
}

View File

@ -0,0 +1,85 @@
/*++
Copyright (c) 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.
Module Name:
Reset.h
Abstract:
some definitions for reset
--*/
#ifndef _KBC_RESET_H
#define _KBC_RESET_H
#include <PiDxe.h>
#include <Library/IoLib.h>
#include <Library/DebugLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/Reset.h>
EFI_STATUS
EFIAPI
InitializeReset (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
TODO: Add function description
Arguments:
ImageHandle - TODO: add argument description
SystemTable - TODO: add argument description
Returns:
TODO: add return values
--*/
;
VOID
EFIAPI
KbcResetSystem (
IN EFI_RESET_TYPE ResetType,
IN EFI_STATUS ResetStatus,
IN UINTN DataSize,
IN CHAR16 *ResetData OPTIONAL
)
/*++
Routine Description:
TODO: Add function description
Arguments:
ResetType - TODO: add argument description
ResetStatus - TODO: add argument description
DataSize - TODO: add argument description
ResetData - TODO: add argument description
Returns:
TODO: add return values
--*/
;
#endif

View File

@ -0,0 +1,59 @@
#/*++
#
# Copyright (c) 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.
#
# Module Name:
# Reset.inf
#
# Abstract:
#
#--*/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = KbcReset
FILE_GUID = 6F0198AA-1F1D-426D-AE3E-39AB633FCC28
MODULE_TYPE = DXE_RUNTIME_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = InitializeReset
[Packages]
DuetPkg/DuetPkg.dec
MdePkg/MdePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
[LibraryClasses]
DebugLib
UefiBootServicesTableLib
UefiDriverEntryPoint
IoLib
[Sources.common]
Reset.c
Reset.h
[Sources.ipf]
Ipf\IpfReset.c
[Sources.ia32]
Ia32\Ia32Reset.c
[Sources.x64]
x64\x64Reset.c
[Protocols]
gEfiResetArchProtocolGuid
[Depex]
gEfiCpuIoProtocolGuid

View File

@ -0,0 +1,79 @@
/*++
Copyright (c) 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.
Module Name:
x64Reset.c
Abstract:
--*/
#include "Reset.h"
//
// The handle onto which the Reset Architectural Protocol is installed
//
EFI_HANDLE mResetHandle = NULL;
EFI_STATUS
EFIAPI
InitializeReset (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Initialize the state information for the Reset Architectural Protocol
Arguments:
ImageHandle of the loaded driver
Pointer to the System Table
Returns:
Status
EFI_SUCCESS - thread can be successfully created
EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
EFI_DEVICE_ERROR - cannot create the timer service
--*/
// TODO: SystemTable - add argument and description to function comment
{
EFI_STATUS Status;
//
// Make sure the Reset Architectural Protocol is not already installed in the system
//
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiResetArchProtocolGuid);
//
// Hook the runtime service table
//
SystemTable->RuntimeServices->ResetSystem = KbcResetSystem;
//
// Now install the Reset RT AP on a new handle
//
Status = gBS->InstallMultipleProtocolInterfaces (
&mResetHandle,
&gEfiResetArchProtocolGuid,
NULL,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@ -0,0 +1,27 @@
/*++
Copyright (c) 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.
Module Name:
x64Reset.dxs
Abstract:
Dependency expression source file.
--*/
#include "EfiDepex.h"
#include EFI_PROTOCOL_DEFINITION (CpuIO)
DEPENDENCY_START
EFI_CPU_IO_PROTOCOL_GUID
DEPENDENCY_END

View File

@ -0,0 +1,201 @@
/*++
Copyright (c) 2005, 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.
Module Name:
LegacyMetronome.c
Abstract:
This contains the installation function for the driver.
--*/
#include "Metronome.h"
//
// Handle for the Metronome Architectural Protocol instance produced by this driver
//
EFI_HANDLE mMetronomeHandle = NULL;
//
// The Metronome Architectural Protocol instance produced by this driver
//
EFI_METRONOME_ARCH_PROTOCOL mMetronome = {
WaitForTick,
TICK_PERIOD
};
//
// The CPU I/O Protocol used to access system hardware
//
EFI_CPU_IO_PROTOCOL *mCpuIo = NULL;
//
// Worker Functions
//
VOID
IoWrite8 (
UINT16 Port,
UINT8 Data
)
/*++
Routine Description:
Write an 8 bit value to an I/O port and save it to the S3 script
Arguments:
Returns:
None.
--*/
// TODO: Port - add argument and description to function comment
// TODO: Data - add argument and description to function comment
{
mCpuIo->Io.Write (
mCpuIo,
EfiCpuIoWidthUint8,
Port,
1,
&Data
);
}
UINT8
ReadRefresh (
VOID
)
/*++
Routine Description:
Read the refresh bit from the REFRESH_PORT
Arguments:
Returns:
None.
--*/
{
UINT8 Data;
mCpuIo->Io.Read (
mCpuIo,
EfiCpuIoWidthUint8,
REFRESH_PORT,
1,
&Data
);
return (UINT8) (Data & REFRESH_ON);
}
EFI_STATUS
EFIAPI
WaitForTick (
IN EFI_METRONOME_ARCH_PROTOCOL *This,
IN UINT32 TickNumber
)
/*++
Routine Description:
Waits for the TickNumber of ticks from a known platform time source.
Arguments:
This Pointer to the protocol instance.
Returns:
EFI_SUCCESS If number of ticks occurred.
EFI_NOT_FOUND Could not locate CPU IO protocol
--*/
// TODO: TickNumber - add argument and description to function comment
{
//
// Wait for TickNumber toggles of the Refresh bit
//
for (; TickNumber != 0x00; TickNumber--) {
while (ReadRefresh () == REFRESH_ON)
;
while (ReadRefresh () == REFRESH_OFF)
;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
InstallMetronome (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Install the LegacyMetronome driver. Loads a Metronome Arch Protocol based
on the Port 61 timer.
Arguments:
(Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
Returns:
EFI_SUCCESS - Metronome Architectural Protocol Installed
--*/
// TODO: ImageHandle - add argument and description to function comment
// TODO: SystemTable - add argument and description to function comment
{
EFI_STATUS Status;
//
// Make sure the Metronome Architectural Protocol is not already installed in the system
//
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiMetronomeArchProtocolGuid);
//
// Get the CPU I/O Protocol that this driver requires
// If the CPU I/O Protocol is not found, then ASSERT because the dependency expression
// should guarantee that it is present in the handle database.
//
Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, &mCpuIo);
ASSERT_EFI_ERROR (Status);
//
// Program port 61 timer 1 as refresh timer. We could use ACPI timer in the
// future.
//
IoWrite8 (TIMER1_CONTROL_PORT, LOAD_COUNTER1_LSB);
IoWrite8 (TIMER1_COUNT_PORT, COUNTER1_COUNT);
//
// Install on a new handle
//
Status = gBS->InstallMultipleProtocolInterfaces (
&mMetronomeHandle,
&gEfiMetronomeArchProtocolGuid,
&mMetronome,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@ -0,0 +1,28 @@
/*++
Copyright (c) 2005, 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.
Module Name:
LegacyMetronome.dxs
Abstract:
Dependency expression source file.
--*/
#include "EfiDepex.h"
#include EFI_PROTOCOL_DEFINITION (CpuIo)
DEPENDENCY_START
EFI_CPU_IO_PROTOCOL_GUID
DEPENDENCY_END

View File

@ -0,0 +1,75 @@
/*++
Copyright (c) 2005, 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.
Module Name:
LegacyMetronome.h
Abstract:
Driver implementing the EFI 2.0 metronome protocol using the legacy PORT 61
timer.
--*/
#ifndef _LEGACY_METRONOME_H
#define _LEGACY_METRONOME_H
//
// Statements that include other files
//
#include <PiDxe.h>
#include <Protocol/CpuIo.h>
#include <Protocol/Metronome.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
//
// Private definitions
//
#define TICK_PERIOD 300
#define REFRESH_PORT 0x61
#define REFRESH_ON 0x10
#define REFRESH_OFF 0x00
#define TIMER1_CONTROL_PORT 0x43
#define TIMER1_COUNT_PORT 0x41
#define LOAD_COUNTER1_LSB 0x54
#define COUNTER1_COUNT 0x12
//
// Function Prototypes
//
EFI_STATUS
EFIAPI
WaitForTick (
IN EFI_METRONOME_ARCH_PROTOCOL *This,
IN UINT32 TickNumber
)
/*++
Routine Description:
TODO: Add function description
Arguments:
This - TODO: add argument description
TickNumber - TODO: add argument description
Returns:
TODO: add return values
--*/
;
#endif

View File

@ -0,0 +1,48 @@
#/*++
#
# Copyright (c) 2005, 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.
#
# Module Name:
#
# Abstract:
#
#--*/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = Metronome
FILE_GUID = 07A9330A-F347-11d4-9A49-0090273FC14D
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = InstallMetronome
[Packages]
MdePkg/MdePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
DuetPkg/DuetPkg.dec
[LibraryClasses]
UefiDriverEntryPoint
DebugLib
UefiBootServicesTableLib
[Sources.common]
Metronome.c
Metronome.h
[Protocols]
gEfiMetronomeArchProtocolGuid
gEfiCpuIoProtocolGuid
[Depex]
gEfiCpuIoProtocolGuid

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,312 @@
/*++
Copyright (c) 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.
Module Name:
BdsPlatform.h
Abstract:
Head file for BDS Platform specific code
--*/
#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
#include <PiDxe.h>
#include <IndustryStandard/Pci.h>
#include <IndustryStandard/Acpi.h>
#include <IndustryStandard/Smbios.h>
#include <IndustryStandard/LegacyBiosMpTable.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseLib.h>
#include <Library/PcdLib.h>
#include <Library/GenericBdsLib.h>
#include <Library/PlatformBdsLib.h>
#include <Library/GraphicsLib.h>
#include <Library/HobLib.h>
#include <Library/UefiLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/DevicePathLib.h>
#include <Protocol/PciIo.h>
#include <Guid/Bmp.h>
#include <Guid/Acpi.h>
#include <Guid/Smbios.h>
#include <Guid/Mps.h>
#include <Guid/HobList.h>
#include <Guid/PciExpressBaseAddress.h>
#include <Guid/GlobalVariable.h>
extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[];
extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[];
extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[];
extern EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[];
extern ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode;
extern ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode;
extern UART_DEVICE_PATH gUartDeviceNode;
extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;
//
//
//
#define VarConsoleInpDev L"ConInDev"
#define VarConsoleInp L"ConIn"
#define VarConsoleOutDev L"ConOutDev"
#define VarConsoleOut L"ConOut"
#define VarErrorOutDev L"ErrOutDev"
#define VarErrorOut L"ErrOut"
#define PCI_DEVICE_PATH_NODE(Func, Dev) \
{ \
HARDWARE_DEVICE_PATH, \
HW_PCI_DP, \
(UINT8) (sizeof (PCI_DEVICE_PATH)), \
(UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8), \
(Func), \
(Dev) \
}
#define PNPID_DEVICE_PATH_NODE(PnpId) \
{ \
ACPI_DEVICE_PATH, \
ACPI_DP, \
(UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
(UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8), \
EISA_PNP_ID((PnpId)), \
0 \
}
#define gPciRootBridge \
PNPID_DEVICE_PATH_NODE(0x0A03)
#define gPciIsaBridge \
PCI_DEVICE_PATH_NODE(0, 0x1f)
#define gP2PBridge \
PCI_DEVICE_PATH_NODE(0, 0x1e)
#define gPnpPs2Keyboard \
PNPID_DEVICE_PATH_NODE(0x0303)
#define gPnp16550ComPort \
PNPID_DEVICE_PATH_NODE(0x0501)
#define gUart \
{ \
MESSAGING_DEVICE_PATH, \
MSG_UART_DP, \
(UINT8) (sizeof (UART_DEVICE_PATH)), \
(UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8), \
0, \
115200, \
8, \
1, \
1 \
}
#define gPcAnsiTerminal \
{ \
MESSAGING_DEVICE_PATH, \
MSG_VENDOR_DP, \
(UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
(UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8), \
DEVICE_PATH_MESSAGING_PC_ANSI \
}
#define gEndEntire \
{ \
END_DEVICE_PATH_TYPE, \
END_ENTIRE_DEVICE_PATH_SUBTYPE, \
END_DEVICE_PATH_LENGTH, \
0 \
}
#define PCI_CLASS_SCC 0x07
#define PCI_SUBCLASS_SERIAL 0x00
#define PCI_IF_16550 0x02
#define IS_PCI_16550SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)
#define EFI_SYSTEM_TABLE_MAX_ADDRESS 0xFFFFFFFF
#define SYS_TABLE_PAD(ptr) (((~ptr) +1) & 0x07 )
//
// Platform Root Bridge
//
typedef struct {
ACPI_HID_DEVICE_PATH PciRootBridge;
EFI_DEVICE_PATH_PROTOCOL End;
} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;
typedef struct {
ACPI_HID_DEVICE_PATH PciRootBridge;
PCI_DEVICE_PATH IsaBridge;
ACPI_HID_DEVICE_PATH Keyboard;
EFI_DEVICE_PATH_PROTOCOL End;
} PLATFORM_DUMMY_ISA_KEYBOARD_DEVICE_PATH;
typedef struct {
ACPI_HID_DEVICE_PATH PciRootBridge;
PCI_DEVICE_PATH IsaBridge;
ACPI_HID_DEVICE_PATH IsaSerial;
UART_DEVICE_PATH Uart;
VENDOR_DEVICE_PATH TerminalType;
EFI_DEVICE_PATH_PROTOCOL End;
} PLATFORM_DUMMY_ISA_SERIAL_DEVICE_PATH;
typedef struct {
ACPI_HID_DEVICE_PATH PciRootBridge;
PCI_DEVICE_PATH VgaDevice;
EFI_DEVICE_PATH_PROTOCOL End;
} PLATFORM_DUMMY_PCI_VGA_DEVICE_PATH;
typedef struct {
ACPI_HID_DEVICE_PATH PciRootBridge;
PCI_DEVICE_PATH PciBridge;
PCI_DEVICE_PATH SerialDevice;
UART_DEVICE_PATH Uart;
VENDOR_DEVICE_PATH TerminalType;
EFI_DEVICE_PATH_PROTOCOL End;
} PLATFORM_DUMMY_PCI_SERIAL_DEVICE_PATH;
//
// the short form device path for Usb keyboard
//
#define CLASS_HID 3
#define SUBCLASS_BOOT 1
#define PROTOCOL_KEYBOARD 1
typedef struct {
USB_CLASS_DEVICE_PATH UsbClass;
EFI_DEVICE_PATH_PROTOCOL End;
} USB_CLASS_FORMAT_DEVICE_PATH;
extern PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0;
//
// Platform BDS Functions
//
VOID
PlatformBdsInit (
IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData
)
;
VOID
PlatformBdsPolicyBehavior (
IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData,
IN LIST_ENTRY *DriverOptionList,
IN LIST_ENTRY *BootOptionList
)
;
VOID
PlatformBdsGetDriverOption (
IN LIST_ENTRY *BdsDriverLists
)
;
EFI_STATUS
BdsMemoryTest (
EXTENDMEM_COVERAGE_LEVEL Level
)
;
EFI_STATUS
PlatformBdsShowProgress (
EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
CHAR16 *Title,
EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
UINTN Progress,
UINTN PreviousValue
)
;
VOID
PlatformBdsConnectSequence (
VOID
)
;
VOID
PlatformBdsBootFail (
IN BDS_COMMON_OPTION *Option,
IN EFI_STATUS Status,
IN CHAR16 *ExitData,
IN UINTN ExitDataSize
)
;
VOID
PlatformBdsBootSuccess (
IN BDS_COMMON_OPTION *Option
)
;
EFI_STATUS
ProcessCapsules (
EFI_BOOT_MODE BootMode
)
;
EFI_STATUS
PlatformBdsConnectConsole (
IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
)
;
EFI_STATUS
PlatformBdsNoConsoleAction (
VOID
)
;
EFI_STATUS
ConvertMpsTable (
IN OUT VOID **Table
)
;
EFI_STATUS
ConvertSmbiosTable (
IN OUT VOID **Table
)
;
EFI_STATUS
ConvertAcpiTable (
IN UINTN TableLen,
IN OUT VOID **Table
)
;
EFI_STATUS
ConvertSystemTable (
IN EFI_GUID *TableGuid,
IN OUT VOID **Table
)
;
VOID
PlatformBdsEnterFrontPage (
IN UINT16 TimeoutDefault,
IN BOOLEAN ConnectAllHappened
)
;
#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_

View File

@ -0,0 +1,64 @@
#/*++
#
# Copyright (c) 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.
#
# Module Name:
#
# PlatformBds.inf
#
# Abstract:
#
# Component description file for Bds module.
#
#--*/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = DuetBds
FILE_GUID = A6F691AC-31C8-4444-854C-E2C1A6950F92
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x0002000A
[Sources.common]
BdsPlatform.c
PlatformData.c
BdsPlatform.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
Nt32Pkg/Nt32Pkg.dec
DuetPkg/DuetPkg.dec
[LibraryClasses]
BaseLib
MemoryAllocationLib
UefiBootServicesTableLib
BaseMemoryLib
DebugLib
PcdLib
GraphicsLib
GenericBdsLib
HobLib
UefiLib
DevicePathLib
[Guids]
gEfiDefaultBmpLogoGuid
gEfiGlobalVariableGuid
gEfiPciExpressBaseAddressGuid
gEfiAcpi20TableGuid
gEfiMpsTableGuid
gEfiSmbiosTableGuid
gEfiAcpiTableGuid

View File

@ -0,0 +1,157 @@
/*++
Copyright (c) 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.
Module Name:
PlatformData.c
Abstract:
Defined the platform specific device path which will be used by
platform Bbd to perform the platform policy connect.
--*/
#include "BdsPlatform.h"
//
// Predefined platform default time out value
//
UINT16 gPlatformBootTimeOutDefault = 3;
ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;
ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;
UART_DEVICE_PATH gUartDeviceNode = gUart;
VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;
//
// Predefined platform root bridge
//
PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = {
gPciRootBridge,
gEndEntire
};
EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[] = {
(EFI_DEVICE_PATH_PROTOCOL *) &gPlatformRootBridge0,
NULL
};
USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = {
{
{
MESSAGING_DEVICE_PATH,
MSG_USB_CLASS_DP,
(UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),
(UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
},
0xffff, // VendorId
0xffff, // ProductId
CLASS_HID, // DeviceClass
SUBCLASS_BOOT, // DeviceSubClass
PROTOCOL_KEYBOARD // DeviceProtocol
},
{
END_DEVICE_PATH_TYPE,
END_ENTIRE_DEVICE_PATH_SUBTYPE,
END_DEVICE_PATH_LENGTH,
0
}
};
/*
//
// Platform specific Dummy ISA keyboard device path
//
PLATFORM_DUMMY_ISA_KEYBOARD_DEVICE_PATH gDummyIsaKeyboardDevicePath = {
gPciRootBridge,
gPciIsaBridge,
gPnpPs2Keyboard,
gEndEntire
};
//
// Platform specific Dummy ISA serial device path
//
PLATFORM_DUMMY_ISA_SERIAL_DEVICE_PATH gDummyIsaSerialDevicePath = {
gPciRootBridge,
gPciIsaBridge,
gPnp16550ComPort,
gUart,
gPcAnsiTerminal,
gEndEntire
};
//
// Platform specific Dummy PCI VGA device path
//
PLATFORM_DUMMY_PCI_VGA_DEVICE_PATH gDummyPciVgaDevicePath = {
gPciRootBridge,
PCI_DEVICE_PATH_NODE(0, 0x2),
gEndEntire
};
//
// Platform specific Dummy PCI serial device path
//
PLATFORM_DUMMY_PCI_SERIAL_DEVICE_PATH gDummyPciSerialDevicePath = {
gPciRootBridge,
gP2PBridge,
PCI_DEVICE_PATH_NODE(0, 0x0),
gUart,
gPcAnsiTerminal,
gEndEntire
};
*/
//
// Predefined platform default console device path
//
BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {
//
// need update dynamically
//
// {
// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyIsaSerialDevicePath,
// (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
// },
// {
// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyIsaKeyboardDevicePath,
// (CONSOLE_IN | STD_ERROR)
// },
// {
// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyPciVgaDevicePath,
// CONSOLE_OUT
// },
// {
// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyPciSerialDevicePath,
// (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
// },
{
(EFI_DEVICE_PATH_PROTOCOL*) &gUsbClassKeyboardDevicePath,
CONSOLE_IN
},
{
NULL,
0
}
};
//
// Predefined platform specific driver option
//
EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[] = { NULL };
//
// Predefined platform connect sequence
//
EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };

View File

@ -0,0 +1,170 @@
/*++
Copyright (c) 2005, 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.
Module Name:
Ia32PcRtc.c
Abstract:
--*/
#include "RealTimeClock.h"
static PC_RTC_MODULE_GLOBALS mModuleGlobal;
EFI_STATUS
EFIAPI
PcRtcEfiGetTime (
OUT EFI_TIME *Time,
OUT EFI_TIME_CAPABILITIES *Capabilities
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Time - TODO: add argument description
Capabilities - TODO: add argument description
Returns:
TODO: add return values
--*/
{
return PcRtcGetTime (Time, Capabilities, &mModuleGlobal);
}
EFI_STATUS
EFIAPI
PcRtcEfiSetTime (
IN EFI_TIME *Time
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Time - TODO: add argument description
Returns:
TODO: add return values
--*/
{
return PcRtcSetTime (Time, &mModuleGlobal);
}
EFI_STATUS
EFIAPI
PcRtcEfiGetWakeupTime (
OUT BOOLEAN *Enabled,
OUT BOOLEAN *Pending,
OUT EFI_TIME *Time
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Enabled - TODO: add argument description
Pending - TODO: add argument description
Time - TODO: add argument description
Returns:
TODO: add return values
--*/
{
return PcRtcGetWakeupTime (Enabled, Pending, Time, &mModuleGlobal);
}
EFI_STATUS
EFIAPI
PcRtcEfiSetWakeupTime (
IN BOOLEAN Enabled,
OUT EFI_TIME *Time
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Enabled - TODO: add argument description
Time - TODO: add argument description
Returns:
TODO: add return values
--*/
{
return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal);
}
EFI_STATUS
EFIAPI
InitializeRealTimeClock (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: ImageHandle - add argument and description to function comment
// TODO: SystemTable - add argument and description to function comment
{
EFI_STATUS Status;
EFI_HANDLE NewHandle;
EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_HIGH_LEVEL);
Status = PcRtcInit (&mModuleGlobal);
if (EFI_ERROR (Status)) {
return Status;
}
SystemTable->RuntimeServices->GetTime = PcRtcEfiGetTime;
SystemTable->RuntimeServices->SetTime = PcRtcEfiSetTime;
SystemTable->RuntimeServices->GetWakeupTime = PcRtcEfiGetWakeupTime;
SystemTable->RuntimeServices->SetWakeupTime = PcRtcEfiSetWakeupTime;
NewHandle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&NewHandle,
&gEfiRealTimeClockArchProtocolGuid,
NULL,
NULL
);
return Status;
}

View File

@ -0,0 +1,29 @@
/*++
Copyright (c) 2005, 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.
Module Name:
Ia32PcRtc.dxs
Abstract:
Dependency expression source file.
--*/
#include "EfiDepex.h"
#include EFI_ARCH_PROTOCOL_DEFINITION (Cpu)
#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
#include EFI_PROTOCOL_DEFINITION (CpuIo)
DEPENDENCY_START
EFI_CPU_ARCH_PROTOCOL_GUID AND EFI_METRONOME_ARCH_PROTOCOL_GUID AND EFI_CPU_IO_PROTOCOL_GUID
DEPENDENCY_END

View File

@ -0,0 +1,185 @@
/*++
Copyright (c) 2005, 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.
Module Name:
IpfPcRtc.c
Abstract:
Register the extended SAL infrastructure.
Make the EFI RT APIs call extended SAL calls via the RT lib wrappers.
We can not do this on IA-32 as RT lib wrappers call via rRT.
--*/
#include "RealTimeClock.h"
//
// Don't use directly after virtual address have been registered.
//
static PC_RTC_MODULE_GLOBALS mModuleGlobal;
SAL_RETURN_REGS
PcRtcEsalServicesClassCommonEntry (
IN UINT64 FunctionId,
IN UINT64 Arg2,
IN UINT64 Arg3,
IN UINT64 Arg4,
IN UINT64 Arg5,
IN UINT64 Arg6,
IN UINT64 Arg7,
IN UINT64 Arg8,
IN SAL_EXTENDED_SAL_PROC ExtendedSalProc,
IN BOOLEAN VirtualMode,
IN PC_RTC_MODULE_GLOBALS *Global
)
/*++
Routine Description:
Main entry for Extended SAL Reset Services
Arguments:
FunctionId Function Id which needed to be called.
Arg2 EFI_RESET_TYPE, whether WARM of COLD reset
Arg3 Last EFI_STATUS
Arg4 Data Size of UNICODE STRING passed in ARG5
Arg5 Unicode String which CHAR16*
Returns:
SAL_RETURN_REGS
--*/
// TODO: Arg6 - add argument and description to function comment
// TODO: Arg7 - add argument and description to function comment
// TODO: Arg8 - add argument and description to function comment
// TODO: ExtendedSalProc - add argument and description to function comment
// TODO: VirtualMode - add argument and description to function comment
// TODO: Global - add argument and description to function comment
{
EFI_STATUS EfiStatus;
SAL_RETURN_REGS ReturnVal;
switch (FunctionId) {
case GetTime:
EfiStatus = PcRtcGetTime ((EFI_TIME *) Arg2, (EFI_TIME_CAPABILITIES *) Arg3, Global);
break;
case SetTime:
EfiStatus = PcRtcSetTime ((EFI_TIME *) Arg2, Global);
break;
case GetWakeupTime:
EfiStatus = PcRtcGetWakeupTime ((BOOLEAN *) Arg2, (BOOLEAN *) Arg3, (EFI_TIME *) Arg4, Global);
break;
case SetWakeupTime:
EfiStatus = PcRtcSetWakeupTime ((BOOLEAN) Arg2, (EFI_TIME *) Arg3, Global);
break;
case InitializeThreshold:
EfiStatus = EFI_SAL_NOT_IMPLEMENTED;
break;
case BumpThresholdCount:
EfiStatus = EFI_SAL_NOT_IMPLEMENTED;
break;
case GetThresholdCount:
EfiStatus = EFI_SAL_NOT_IMPLEMENTED;
break;
case GetRtcFreq:
EfiStatus = EFI_SAL_NOT_IMPLEMENTED;
break;
default:
EfiStatus = EFI_SAL_INVALID_ARGUMENT;
break;;
}
ReturnVal.Status = EfiStatus;
return ReturnVal;
}
EFI_STATUS
EFIAPI
InitializePcRtc (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: ImageHandle - add argument and description to function comment
// TODO: SystemTable - add argument and description to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
EFI_TIME Time;
EFI_TIME_CAPABILITIES Capabilities;
EFI_STATUS EfiStatus;
EfiInitializeRuntimeDriverLib (ImageHandle, SystemTable, NULL);
EfiInitializeLock (&mModuleGlobal.RtcLock, EFI_TPL_HIGH_LEVEL);
EfiStatus = PcRtcInit (&mModuleGlobal);
if (EFI_ERROR (EfiStatus)) {
return EfiStatus;
}
RegisterEsalClass (
&gEfiExtendedSalRtcServicesProtocolGuid,
&mModuleGlobal,
PcRtcEsalServicesClassCommonEntry,
GetTime,
PcRtcEsalServicesClassCommonEntry,
SetTime,
PcRtcEsalServicesClassCommonEntry,
GetWakeupTime,
PcRtcEsalServicesClassCommonEntry,
SetWakeupTime,
PcRtcEsalServicesClassCommonEntry,
GetRtcFreq,
PcRtcEsalServicesClassCommonEntry,
InitializeThreshold,
PcRtcEsalServicesClassCommonEntry,
BumpThresholdCount,
PcRtcEsalServicesClassCommonEntry,
GetThresholdCount,
NULL
);
//
// the following code is to initialize the RTC fields in case the values read
// back from CMOS are invalid at the first time.
//
EfiStatus = PcRtcGetTime (&Time, &Capabilities, &mModuleGlobal);
if (EFI_ERROR (EfiStatus)) {
Time.Second = RTC_INIT_SECOND;
Time.Minute = RTC_INIT_MINUTE;
Time.Hour = RTC_INIT_HOUR;
Time.Day = RTC_INIT_DAY;
Time.Month = RTC_INIT_MONTH;
Time.Year = RTC_INIT_YEAR;
PcRtcSetTime (&Time, &mModuleGlobal);
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,28 @@
/*++
Copyright (c) 2005, 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.
Module Name:
IpfPcRtc.dxs
Abstract:
Dependency expression source file.
--*/
#include "EfiDepex.h"
#include EFI_PROTOCOL_DEFINITION (ExtendedSalGuid)
#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
DEPENDENCY_START
EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID AND EFI_METRONOME_ARCH_PROTOCOL_GUID
DEPENDENCY_END

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,491 @@
/*++
Copyright (c) 2005, 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.
Module Name:
PcRtc.h
Abstract:
Include for real time clock driver
Revision History
--*/
#ifndef _RTC_H_
#define _RTC_H_
#include <FrameworkDxe.h>
#include <Protocol/RealTimeClock.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/IoLib.h>
#include <Library/TimerLib.h>
#include <Library/BaseMemoryLib.h>
typedef struct {
EFI_LOCK RtcLock;
UINT16 SavedTimeZone;
UINT8 Daylight;
} PC_RTC_MODULE_GLOBALS;
#define PCAT_RTC_ADDRESS_REGISTER 0x70
#define PCAT_RTC_DATA_REGISTER 0x71
//
// Dallas DS12C887 Real Time Clock
//
#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59
#define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59
#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59
#define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59
#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
#define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
#define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7
#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31
#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12
#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99
#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]
#define RTC_ADDRESS_REGISTER_B 11 // R/W
#define RTC_ADDRESS_REGISTER_C 12 // RO
#define RTC_ADDRESS_REGISTER_D 13 // RO
#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W
//
// Date and time initial values.
// They are used if the RTC values are invalid during driver initialization
//
#define RTC_INIT_SECOND 0
#define RTC_INIT_MINUTE 0
#define RTC_INIT_HOUR 0
#define RTC_INIT_DAY 1
#define RTC_INIT_MONTH 1
#define RTC_INIT_YEAR 2001
//
// Register initial values
//
#define RTC_INIT_REGISTER_A 0x26
#define RTC_INIT_REGISTER_B 0x02
#define RTC_INIT_REGISTER_D 0x0
#pragma pack(1)
//
// Register A
//
typedef struct {
UINT8 RS : 4; // Rate Selection Bits
UINT8 DV : 3; // Divisor
UINT8 UIP : 1; // Update in progress
} RTC_REGISTER_A_BITS;
typedef union {
RTC_REGISTER_A_BITS Bits;
UINT8 Data;
} RTC_REGISTER_A;
//
// Register B
//
typedef struct {
UINT8 DSE : 1; // 0 - Daylight saving disabled 1 - Daylight savings enabled
UINT8 MIL : 1; // 0 - 12 hour mode 1 - 24 hour mode
UINT8 DM : 1; // 0 - BCD Format 1 - Binary Format
UINT8 SQWE : 1; // 0 - Disable SQWE output 1 - Enable SQWE output
UINT8 UIE : 1; // 0 - Update INT disabled 1 - Update INT enabled
UINT8 AIE : 1; // 0 - Alarm INT disabled 1 - Alarm INT Enabled
UINT8 PIE : 1; // 0 - Periodic INT disabled 1 - Periodic INT Enabled
UINT8 SET : 1; // 0 - Normal operation. 1 - Updates inhibited
} RTC_REGISTER_B_BITS;
typedef union {
RTC_REGISTER_B_BITS Bits;
UINT8 Data;
} RTC_REGISTER_B;
//
// Register C
//
typedef struct {
UINT8 Reserved : 4; // Read as zero. Can not be written.
UINT8 UF : 1; // Update End Interrupt Flag
UINT8 AF : 1; // Alarm Interrupt Flag
UINT8 PF : 1; // Periodic Interrupt Flag
UINT8 IRQF : 1; // Iterrupt Request Flag = PF & PIE | AF & AIE | UF & UIE
} RTC_REGISTER_C_BITS;
typedef union {
RTC_REGISTER_C_BITS Bits;
UINT8 Data;
} RTC_REGISTER_C;
//
// Register D
//
typedef struct {
UINT8 Reserved : 7; // Read as zero. Can not be written.
UINT8 VRT : 1; // Valid RAM and Time
} RTC_REGISTER_D_BITS;
typedef union {
RTC_REGISTER_D_BITS Bits;
UINT8 Data;
} RTC_REGISTER_D;
#pragma pack()
EFI_STATUS
PcRtcInit (
IN PC_RTC_MODULE_GLOBALS *Global
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Global - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
PcRtcSetTime (
IN EFI_TIME *Time,
IN PC_RTC_MODULE_GLOBALS *Global
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Time - TODO: add argument description
Global - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
PcRtcGetTime (
OUT EFI_TIME *Time,
IN EFI_TIME_CAPABILITIES *Capabilities,
IN PC_RTC_MODULE_GLOBALS *Global
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Time - TODO: add argument description
Capabilities - TODO: add argument description
Global - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
EFIAPI
PcRtcSetWakeupTime (
IN BOOLEAN Enable,
OUT EFI_TIME *Time,
IN PC_RTC_MODULE_GLOBALS *Global
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Enable - TODO: add argument description
Time - TODO: add argument description
Global - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
EFIAPI
PcRtcGetWakeupTime (
OUT BOOLEAN *Enabled,
OUT BOOLEAN *Pending,
OUT EFI_TIME *Time,
IN PC_RTC_MODULE_GLOBALS *Global
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Enabled - TODO: add argument description
Pending - TODO: add argument description
Time - TODO: add argument description
Global - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
EFIAPI
InitializePcRtc (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
TODO: Add function description
Arguments:
ImageHandle - TODO: add argument description
SystemTable - TODO: add argument description
Returns:
TODO: add return values
--*/
;
UINT8
BcdToDecimal (
IN UINT8 BcdValue
)
/*++
Routine Description:
TODO: Add function description
Arguments:
BcdValue - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
RtcTimeFieldsValid (
IN EFI_TIME *Time
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Time - TODO: add argument description
Returns:
TODO: add return values
--*/
;
UINT8
DecimaltoBcd (
IN UINT8 DecValue
)
/*++
Routine Description:
TODO: Add function description
Arguments:
DecValue - TODO: add argument description
Returns:
TODO: add return values
--*/
;
VOID
ConvertEfiTimeToRtcTime (
IN EFI_TIME *Time,
IN RTC_REGISTER_B RegisterB,
IN UINT8 *Century
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Time - TODO: add argument description
RegisterB - TODO: add argument description
Century - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
RtcTestCenturyRegister (
VOID
)
/*++
Routine Description:
TODO: Add function description
Arguments:
None
Returns:
TODO: add return values
--*/
;
VOID
ConvertRtcTimeToEfiTime (
IN EFI_TIME *Time,
IN RTC_REGISTER_B RegisterB
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Time - TODO: add argument description
RegisterB - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
RtcWaitToUpdate (
UINTN Timeout
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Timeout - TODO: add argument description
Returns:
TODO: add return values
--*/
;
UINT8
RtcSaveContext (
IN PC_RTC_MODULE_GLOBALS *Global
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Global - TODO: add argument description
Returns:
TODO: add return values
--*/
;
VOID
RtcRestoreContext (
IN UINT8 SavedAddressRegister,
IN PC_RTC_MODULE_GLOBALS *Global
)
/*++
Routine Description:
TODO: Add function description
Arguments:
SavedAddressRegister - TODO: add argument description
Global - TODO: add argument description
Returns:
TODO: add return values
--*/
;
#endif

View File

@ -0,0 +1,63 @@
#/*++
#
# Copyright (c) 2005, 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.
#
# Module Name:
#
# Abstract:
#
#--*/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = RealTimeClock
FILE_GUID = 378D7B65-8DA9-4773-B6E4-A47826A833E1
MODULE_TYPE = DXE_RUNTIME_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = InitializeRealTimeClock
[Packages]
MdePkg/MdePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
DuetPkg/DuetPkg.dec
[LibraryClasses]
UefiDriverEntryPoint
UefiBootServicesTableLib
UefiLib
IoLib
TimerLib
BaseMemoryLib
[Sources.common]
RealTimeClock.c
RealTimeClock.h
[Sources.ia32]
Ia32/RealTimeClock.c
[Sources.x64]
x64/RealTimeClock.c
[Sources.ipf]
Ipf/RealTimeClock.c
[Protocols]
gEfiCpuArchProtocolGuid
gEfiMetronomeArchProtocolGuid
gEfiCpuIoProtocolGuid
gEfiRealTimeClockArchProtocolGuid
[Depex]
gEfiCpuArchProtocolGuid AND gEfiMetronomeArchProtocolGuid AND gEfiCpuIoProtocolGuid

View File

@ -0,0 +1,170 @@
/*++
Copyright (c) 2005, 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.
Module Name:
x64PcRtc.c
Abstract:
--*/
#include "RealTimeClock.h"
static PC_RTC_MODULE_GLOBALS mModuleGlobal;
EFI_STATUS
EFIAPI
PcRtcEfiGetTime (
OUT EFI_TIME *Time,
OUT EFI_TIME_CAPABILITIES *Capabilities
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Time - TODO: add argument description
Capabilities - TODO: add argument description
Returns:
TODO: add return values
--*/
{
return PcRtcGetTime (Time, Capabilities, &mModuleGlobal);
}
EFI_STATUS
EFIAPI
PcRtcEfiSetTime (
IN EFI_TIME *Time
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Time - TODO: add argument description
Returns:
TODO: add return values
--*/
{
return PcRtcSetTime (Time, &mModuleGlobal);
}
EFI_STATUS
EFIAPI
PcRtcEfiGetWakeupTime (
OUT BOOLEAN *Enabled,
OUT BOOLEAN *Pending,
OUT EFI_TIME *Time
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Enabled - TODO: add argument description
Pending - TODO: add argument description
Time - TODO: add argument description
Returns:
TODO: add return values
--*/
{
return PcRtcGetWakeupTime (Enabled, Pending, Time, &mModuleGlobal);
}
EFI_STATUS
EFIAPI
PcRtcEfiSetWakeupTime (
IN BOOLEAN Enabled,
OUT EFI_TIME *Time
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Enabled - TODO: add argument description
Time - TODO: add argument description
Returns:
TODO: add return values
--*/
{
return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal);
}
EFI_STATUS
EFIAPI
InitializeRealTimeClock (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: ImageHandle - add argument and description to function comment
// TODO: SystemTable - add argument and description to function comment
{
EFI_STATUS Status;
EFI_HANDLE NewHandle;
EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_HIGH_LEVEL);
Status = PcRtcInit (&mModuleGlobal);
if (EFI_ERROR (Status)) {
return Status;
}
SystemTable->RuntimeServices->GetTime = PcRtcEfiGetTime;
SystemTable->RuntimeServices->SetTime = PcRtcEfiSetTime;
SystemTable->RuntimeServices->GetWakeupTime = PcRtcEfiGetWakeupTime;
SystemTable->RuntimeServices->SetWakeupTime = PcRtcEfiSetWakeupTime;
NewHandle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&NewHandle,
&gEfiRealTimeClockArchProtocolGuid,
NULL,
NULL
);
return Status;
}

View File

@ -0,0 +1,29 @@
/*++
Copyright (c) 2005, 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.
Module Name:
x64PcRtc.dxs
Abstract:
Dependency expression source file.
--*/
#include "EfiDepex.h"
#include EFI_ARCH_PROTOCOL_DEFINITION (Cpu)
#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
#include EFI_PROTOCOL_DEFINITION (CpuIo)
DEPENDENCY_START
EFI_CPU_ARCH_PROTOCOL_GUID AND EFI_METRONOME_ARCH_PROTOCOL_GUID AND EFI_CPU_IO_PROTOCOL_GUID
DEPENDENCY_END

View File

@ -0,0 +1,845 @@
/*++
Copyright (c) 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.
Module Name:
DeviceIo.c
Abstract:
EFI PC-AT PCI Device IO driver
--*/
#include "PcatPciRootBridge.h"
#include "DeviceIo.h"
EFI_STATUS
DeviceIoConstructor (
IN EFI_HANDLE Handle,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN UINT16 PrimaryBus,
IN UINT16 SubordinateBus
)
/*++
Routine Description:
Initialize and install a Device IO protocol on a empty device path handle.
Arguments:
Handle - Handle of PCI RootBridge IO instance
PciRootBridgeIo - PCI RootBridge IO instance
DevicePath - Device Path of PCI RootBridge IO instance
PrimaryBus - Primary Bus
SubordinateBus - Subordinate Bus
Returns:
EFI_SUCCESS - This driver is added to ControllerHandle.
EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
Others - This driver does not support this device.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
//
// Initialize the Device IO device instance.
//
Private = AllocateZeroPool (sizeof (DEVICE_IO_PRIVATE_DATA));
if (Private == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Private->Signature = DEVICE_IO_PRIVATE_DATA_SIGNATURE;
Private->Handle = Handle;
Private->PciRootBridgeIo = PciRootBridgeIo;
Private->DevicePath = DevicePath;
Private->PrimaryBus = PrimaryBus;
Private->SubordinateBus = SubordinateBus;
Private->DeviceIo.Mem.Read = DeviceIoMemRead;
Private->DeviceIo.Mem.Write = DeviceIoMemWrite;
Private->DeviceIo.Io.Read = DeviceIoIoRead;
Private->DeviceIo.Io.Write = DeviceIoIoWrite;
Private->DeviceIo.Pci.Read = DeviceIoPciRead;
Private->DeviceIo.Pci.Write = DeviceIoPciWrite;
Private->DeviceIo.PciDevicePath = DeviceIoPciDevicePath;
Private->DeviceIo.Map = DeviceIoMap;
Private->DeviceIo.Unmap = DeviceIoUnmap;
Private->DeviceIo.AllocateBuffer = DeviceIoAllocateBuffer;
Private->DeviceIo.Flush = DeviceIoFlush;
Private->DeviceIo.FreeBuffer = DeviceIoFreeBuffer;
//
// Install protocol interfaces for the Device IO device.
//
Status = gBS->InstallMultipleProtocolInterfaces (
&Private->Handle,
&gEfiDeviceIoProtocolGuid,
&Private->DeviceIo,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoMemRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading memory mapped I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if (Width > MMIO_COPY_UINT64) {
return EFI_INVALID_PARAMETER;
}
if (Width >= MMIO_COPY_UINT8) {
Width = Width - MMIO_COPY_UINT8;
Status = Private->PciRootBridgeIo->CopyMem (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
(UINT64) Buffer,
Address,
Count
);
} else {
Status = Private->PciRootBridgeIo->Mem.Read (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
}
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoMemWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing memory mapped I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if (Width > MMIO_COPY_UINT64) {
return EFI_INVALID_PARAMETER;
}
if (Width >= MMIO_COPY_UINT8) {
Width = Width - MMIO_COPY_UINT8;
Status = Private->PciRootBridgeIo->CopyMem (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
(UINT64) Buffer,
Count
);
} else {
Status = Private->PciRootBridgeIo->Mem.Write (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
}
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoIoRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if (Width >= MMIO_COPY_UINT8) {
return EFI_INVALID_PARAMETER;
}
Status = Private->PciRootBridgeIo->Io.Read (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoIoWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if (Width >= MMIO_COPY_UINT8) {
return EFI_INVALID_PARAMETER;
}
Status = Private->PciRootBridgeIo->Io.Write (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoPciRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading PCI configuration space of device
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if (Width < 0 || Width >= MMIO_COPY_UINT8) {
return EFI_INVALID_PARAMETER;
}
Status = Private->PciRootBridgeIo->Pci.Read (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoPciWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing PCI configuration space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if (Width < 0 || Width >= MMIO_COPY_UINT8) {
return EFI_INVALID_PARAMETER;
}
Status = Private->PciRootBridgeIo->Pci.Write (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
return Status;
}
EFI_DEVICE_PATH_PROTOCOL *
AppendPciDevicePath (
IN DEVICE_IO_PRIVATE_DATA *Private,
IN UINT8 Bus,
IN UINT8 Device,
IN UINT8 Function,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN OUT UINT16 *BridgePrimaryBus,
IN OUT UINT16 *BridgeSubordinateBus
)
/*++
Routine Description:
Append a PCI device path node to another device path.
Arguments:
Private - A pointer to DEVICE_IO_PRIVATE_DATA instance.
Bus - PCI bus number of the device.
Device - PCI device number of the device.
Function - PCI function number of the device.
DevicePath - Original device path which will be appended a PCI device path node.
BridgePrimaryBus - Primary bus number of the bridge.
BridgeSubordinateBus - Subordinate bus number of the bridge.
Returns:
Pointer to the appended PCI device path.
--*/
{
UINT16 ThisBus;
UINT8 ThisDevice;
UINT8 ThisFunc;
UINT64 Address;
PCI_TYPE01 PciBridge;
PCI_TYPE01 *PciPtr;
EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;
PCI_DEVICE_PATH PciNode;
PciPtr = &PciBridge;
for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
ZeroMem (PciPtr, sizeof (PCI_TYPE01));
Private->DeviceIo.Pci.Read (
&Private->DeviceIo,
IO_UINT32,
Address,
1,
&(PciPtr->Hdr.VendorId)
);
if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
break;
}
if (PciPtr->Hdr.VendorId == 0xffff) {
continue;
}
Private->DeviceIo.Pci.Read (
&Private->DeviceIo,
IO_UINT32,
Address,
sizeof (PCI_TYPE01) / sizeof (UINT32),
PciPtr
);
if (IS_PCI_BRIDGE (PciPtr)) {
if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {
PciNode.Header.Type = HARDWARE_DEVICE_PATH;
PciNode.Header.SubType = HW_PCI_DP;
SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
PciNode.Device = ThisDevice;
PciNode.Function = ThisFunc;
ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
*BridgePrimaryBus = PciPtr->Bridge.SecondaryBus;
*BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
return ReturnDevicePath;
}
}
if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) {
//
// Skip sub functions, this is not a multi function device
//
break;
}
}
}
}
ZeroMem (&PciNode, sizeof (PciNode));
PciNode.Header.Type = HARDWARE_DEVICE_PATH;
PciNode.Header.SubType = HW_PCI_DP;
SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
PciNode.Device = Device;
PciNode.Function = Function;
ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
*BridgePrimaryBus = 0xffff;
*BridgeSubordinateBus = 0xffff;
return ReturnDevicePath;
}
EFI_STATUS
EFIAPI
DeviceIoPciDevicePath (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN UINT64 Address,
IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
)
/*++
Routine Description:
Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Address - The PCI configuration space address of the device whose Device Path
is going to be returned.
PciDevicePath - A pointer to the pointer for the EFI Device Path for PciAddress.
Memory for the Device Path is allocated from the pool.
Returns:
EFI_SUCCESS - The PciDevicePath returns a pointer to a valid EFI Device Path.
EFI_UNSUPPORTED - The PciAddress does not map to a valid EFI Device Path.
EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
--*/
{
DEVICE_IO_PRIVATE_DATA *Private;
UINT16 PrimaryBus;
UINT16 SubordinateBus;
UINT8 Bus;
UINT8 Device;
UINT8 Func;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
Bus = (UINT8) (((UINT32) Address >> 24) & 0xff);
Device = (UINT8) (((UINT32) Address >> 16) & 0xff);
Func = (UINT8) (((UINT32) Address >> 8) & 0xff);
if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
return EFI_UNSUPPORTED;
}
*PciDevicePath = Private->DevicePath;
PrimaryBus = Private->PrimaryBus;
SubordinateBus = Private->SubordinateBus;
do {
*PciDevicePath = AppendPciDevicePath (
Private,
Bus,
Device,
Func,
*PciDevicePath,
&PrimaryBus,
&SubordinateBus
);
if (*PciDevicePath == NULL) {
return EFI_OUT_OF_RESOURCES;
}
} while (PrimaryBus != 0xffff);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
DeviceIoMap (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_OPERATION_TYPE Operation,
IN EFI_PHYSICAL_ADDRESS *HostAddress,
IN OUT UINTN *NumberOfBytes,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT VOID **Mapping
)
/*++
Routine Description:
Provides the device-specific addresses needed to access system memory.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Operation - Indicates if the bus master is going to read or write to system memory.
HostAddress - The system memory address to map to the device.
NumberOfBytes - On input the number of bytes to map. On output the number of bytes
that were mapped.
DeviceAddress - The resulting map address for the bus master device to use to access the
hosts HostAddress.
Mapping - A resulting value to pass to Unmap().
Returns:
EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.
EFI_DEVICE_ERROR - The system hardware could not map the requested address.
EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if (Operation < 0 || Operation > EfiBusMasterCommonBuffer) {
return EFI_INVALID_PARAMETER;
}
if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
return EFI_UNSUPPORTED;
}
Status = Private->PciRootBridgeIo->Map (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
(VOID *) (UINTN) (*HostAddress),
NumberOfBytes,
DeviceAddress,
Mapping
);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoUnmap (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN VOID *Mapping
)
/*++
Routine Description:
Completes the Map() operation and releases any corresponding resources.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Mapping - The mapping value returned from Map().
Returns:
EFI_SUCCESS - The range was unmapped.
EFI_DEVICE_ERROR - The data was not committed to the target system memory.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
Status = Private->PciRootBridgeIo->Unmap (
Private->PciRootBridgeIo,
Mapping
);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoAllocateBuffer (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress
)
/*++
Routine Description:
Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Type - The type allocation to perform.
MemoryType - The type of memory to allocate, EfiBootServicesData or
EfiRuntimeServicesData.
Pages - The number of pages to allocate.
PhysicalAddress - A pointer to store the base address of the allocated range.
Returns:
EFI_SUCCESS - The requested memory pages were allocated.
EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
EFI_INVALID_PARAMETER - The requested memory type is invalid.
EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on
this platform.
--*/
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS HostAddress;
HostAddress = *PhysicalAddress;
if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
return EFI_INVALID_PARAMETER;
}
if ((Type >= MaxAllocateType) || (Type < AllocateAnyPages)) {
return EFI_INVALID_PARAMETER;
}
if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
return EFI_UNSUPPORTED;
}
if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
Type = AllocateMaxAddress;
HostAddress = MAX_COMMON_BUFFER;
}
Status = gBS->AllocatePages (
Type,
MemoryType,
Pages,
&HostAddress
);
if (EFI_ERROR (Status)) {
return Status;
}
*PhysicalAddress = HostAddress;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
DeviceIoFlush (
IN EFI_DEVICE_IO_PROTOCOL *This
)
/*++
Routine Description:
Flushes any posted write data to the device.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Returns:
EFI_SUCCESS - The buffers were flushed.
EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
Status = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoFreeBuffer (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN UINTN Pages,
IN EFI_PHYSICAL_ADDRESS HostAddress
)
/*++
Routine Description:
Frees pages that were allocated with AllocateBuffer().
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Pages - The number of pages to free.
HostAddress - The base address of the range to free.
Returns:
EFI_SUCCESS - The requested memory pages were freed.
EFI_NOT_FOUND - The requested memory pages were not allocated with
AllocateBuffer().
EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid.
--*/
{
if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
return EFI_INVALID_PARAMETER;
}
return gBS->FreePages (HostAddress, Pages);
}

View File

@ -0,0 +1,449 @@
/*++
Copyright (c) 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.
Module Name:
DeviceIo.h
Abstract:
Private Data definition for Device IO driver
--*/
#ifndef _DEVICE_IO_H
#define _DEVICE_IO_H
#define DEVICE_IO_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('d', 'e', 'v', 'I')
#define MAX_COMMON_BUFFER 0x00000000FFFFFFFF
typedef struct {
UINTN Signature;
EFI_HANDLE Handle;
EFI_DEVICE_IO_PROTOCOL DeviceIo;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
UINT16 PrimaryBus;
UINT16 SubordinateBus;
} DEVICE_IO_PRIVATE_DATA;
#define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE)
EFI_STATUS
DeviceIoConstructor (
IN EFI_HANDLE Handle,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN UINT16 PrimaryBus,
IN UINT16 SubordinateBus
)
/*++
Routine Description:
Initialize and install a Device IO protocol on a empty device path handle.
Arguments:
Handle - Handle of PCI RootBridge IO instance
PciRootBridgeIo - PCI RootBridge IO instance
DevicePath - Device Path of PCI RootBridge IO instance
PrimaryBus - Primary Bus
SubordinateBus - Subordinate Bus
Returns:
EFI_SUCCESS - This driver is added to ControllerHandle.
EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
Others - This driver does not support this device.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoMemRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading memory mapped I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoMemWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing memory mapped I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoIoRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoIoWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoPciRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading PCI configuration space of device
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoPciWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing PCI configuration space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoPciDevicePath (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN UINT64 Address,
IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
)
/*++
Routine Description:
Append a PCI device path node to another device path.
Arguments:
This - A pointer to EFI_DEVICE_IO_PROTOCOL.
Address - PCI bus,device, function.
PciDevicePath - PCI device path.
Returns:
Pointer to the appended PCI device path.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoMap (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_OPERATION_TYPE Operation,
IN EFI_PHYSICAL_ADDRESS *HostAddress,
IN OUT UINTN *NumberOfBytes,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT VOID **Mapping
)
/*++
Routine Description:
Provides the device-specific addresses needed to access system memory.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Operation - Indicates if the bus master is going to read or write to system memory.
HostAddress - The system memory address to map to the device.
NumberOfBytes - On input the number of bytes to map. On output the number of bytes
that were mapped.
DeviceAddress - The resulting map address for the bus master device to use to access the
hosts HostAddress.
Mapping - A resulting value to pass to Unmap().
Returns:
EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.
EFI_DEVICE_ERROR - The system hardware could not map the requested address.
EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoUnmap (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN VOID *Mapping
)
/*++
Routine Description:
Completes the Map() operation and releases any corresponding resources.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Mapping - The mapping value returned from Map().
Returns:
EFI_SUCCESS - The range was unmapped.
EFI_DEVICE_ERROR - The data was not committed to the target system memory.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoAllocateBuffer (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT EFI_PHYSICAL_ADDRESS *HostAddress
)
/*++
Routine Description:
Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Type - The type allocation to perform.
MemoryType - The type of memory to allocate, EfiBootServicesData or
EfiRuntimeServicesData.
Pages - The number of pages to allocate.
HostAddress - A pointer to store the base address of the allocated range.
Returns:
EFI_SUCCESS - The requested memory pages were allocated.
EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
EFI_INVALID_PARAMETER - The requested memory type is invalid.
EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on
this platform.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoFlush (
IN EFI_DEVICE_IO_PROTOCOL *This
)
/*++
Routine Description:
Flushes any posted write data to the device.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Returns:
EFI_SUCCESS - The buffers were flushed.
EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoFreeBuffer (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN UINTN Pages,
IN EFI_PHYSICAL_ADDRESS HostAddress
)
/*++
Routine Description:
Frees pages that were allocated with AllocateBuffer().
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Pages - The number of pages to free.
HostAddress - The base address of the range to free.
Returns:
EFI_SUCCESS - The requested memory pages were freed.
EFI_NOT_FOUND - The requested memory pages were not allocated with
AllocateBuffer().
EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid.
--*/
;
#endif

View File

@ -0,0 +1,734 @@
/*++
Copyright (c) 2005 - 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.
Module Name:
PcatPciRootBridgeIo.c
Abstract:
EFI PC AT PCI Root Bridge Io Protocol
Revision History
--*/
#include "PcatPciRootBridge.h"
static BOOLEAN mPciOptionRomTableInstalled = FALSE;
static EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};
EFI_STATUS
EFIAPI
PcatRootBridgeIoIoRead (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
return gCpuIo->Io.Read (
gCpuIo,
(EFI_CPU_IO_PROTOCOL_WIDTH) Width,
UserAddress,
Count,
UserBuffer
);
}
EFI_STATUS
EFIAPI
PcatRootBridgeIoIoWrite (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
return gCpuIo->Io.Write (
gCpuIo,
(EFI_CPU_IO_PROTOCOL_WIDTH) Width,
UserAddress,
Count,
UserBuffer
);
}
EFI_STATUS
PcatRootBridgeIoGetIoPortMapping (
OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
)
/*++
Get the IO Port Mapping. For IA-32 it is always 0.
--*/
{
*IoPortMapping = 0;
*MemoryPortMapping = 0;
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoPciRW (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN BOOLEAN Write,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
PCI_CONFIG_ACCESS_CF8 Pci;
PCI_CONFIG_ACCESS_CF8 PciAligned;
UINT32 InStride;
UINT32 OutStride;
UINTN PciData;
UINTN PciDataStride;
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
UINT64 PciExpressRegAddr;
BOOLEAN UsePciExpressAccess;
if (Width < 0 || Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
if ((Width & 0x03) >= EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
InStride = 0;
}
if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
OutStride = 0;
}
UsePciExpressAccess = FALSE;
CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
if (PciAddress.ExtendedRegister > 0xFF) {
//
// Check PciExpressBaseAddress
//
if ((PrivateData->PciExpressBaseAddress == 0) ||
(PrivateData->PciExpressBaseAddress >= EFI_MAX_ADDRESS)) {
return EFI_UNSUPPORTED;
} else {
UsePciExpressAccess = TRUE;
}
} else {
if (PciAddress.ExtendedRegister != 0) {
Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;
} else {
Pci.Bits.Reg = PciAddress.Register;
}
//
// Note: We can also use PciExpress access here, if wanted.
//
}
if (!UsePciExpressAccess) {
Pci.Bits.Func = PciAddress.Function;
Pci.Bits.Dev = PciAddress.Device;
Pci.Bits.Bus = PciAddress.Bus;
Pci.Bits.Reserved = 0;
Pci.Bits.Enable = 1;
//
// PCI Config access are all 32-bit alligned, but by accessing the
// CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
// are possible on PCI.
//
// To read a byte of PCI config space you load 0xcf8 and
// read 0xcfc, 0xcfd, 0xcfe, 0xcff
//
PciDataStride = Pci.Bits.Reg & 0x03;
while (Count) {
PciAligned = Pci;
PciAligned.Bits.Reg &= 0xfc;
PciData = (UINTN)PrivateData->PciData + PciDataStride;
EfiAcquireLock(&PrivateData->PciLock);
This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);
if (Write) {
This->Io.Write (This, Width, PciData, 1, UserBuffer);
} else {
This->Io.Read (This, Width, PciData, 1, UserBuffer);
}
EfiReleaseLock(&PrivateData->PciLock);
UserBuffer = ((UINT8 *)UserBuffer) + OutStride;
PciDataStride = (PciDataStride + InStride) % 4;
Pci.Bits.Reg += InStride;
Count -= 1;
}
} else {
//
// Access PCI-Express space by using memory mapped method.
//
PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |
(PciAddress.Bus << 20) |
(PciAddress.Device << 15) |
(PciAddress.Function << 12);
if (PciAddress.ExtendedRegister != 0) {
PciExpressRegAddr += PciAddress.ExtendedRegister;
} else {
PciExpressRegAddr += PciAddress.Register;
}
while (Count) {
if (Write) {
This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
} else {
This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
}
UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
PciExpressRegAddr += InStride;
Count -= 1;
}
}
return EFI_SUCCESS;
}
static
VOID
ScanPciBus(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
EFI_PCI_BUS_SCAN_CALLBACK Callback,
VOID *Context
)
{
UINT16 Bus;
UINT16 Device;
UINT16 Func;
UINT64 Address;
PCI_TYPE00 PciHeader;
//
// Loop through all busses
//
for (Bus = MinBus; Bus <= MaxBus; Bus++) {
//
// Loop 32 devices per bus
//
for (Device = MinDevice; Device <= MaxDevice; Device++) {
//
// Loop through 8 functions per device
//
for (Func = MinFunc; Func <= MaxFunc; Func++) {
//
// Compute the EFI Address required to access the PCI Configuration Header of this PCI Device
//
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
//
// Read the VendorID from this PCI Device's Confioguration Header
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);
//
// If VendorId = 0xffff, there does not exist a device at this
// location. For each device, if there is any function on it,
// there must be 1 function at Function 0. So if Func = 0, there
// will be no more functions in the same device, so we can break
// loop to deal with the next device.
//
if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {
break;
}
if (PciHeader.Hdr.VendorId != 0xffff) {
//
// Read the HeaderType to determine if this is a multi-function device
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);
//
// Call the callback function for the device that was found
//
Callback(
IoDev,
MinBus, MaxBus,
MinDevice, MaxDevice,
MinFunc, MaxFunc,
Bus,
Device,
Func,
Context
);
//
// If this is not a multi-function device, we can leave the loop
// to deal with the next device.
//
if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {
break;
}
}
}
}
}
}
static
VOID
CheckForRom (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
EFI_STATUS Status;
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
PCI_TYPE00 PciHeader;
PCI_TYPE01 *PciBridgeHeader;
UINT32 Register;
UINT32 RomBar;
UINT32 RomBarSize;
EFI_PHYSICAL_ADDRESS RomBuffer;
UINT32 MaxRomSize;
EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;
PCI_DATA_STRUCTURE Pcir;
EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;
BOOLEAN LastImage;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
//
// Save the contents of the PCI Configuration Header
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
if (IS_PCI_BRIDGE(&PciHeader)) {
PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);
//
// See if the PCI-PCI Bridge has its secondary interface enabled.
//
if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {
//
// Disable the Prefetchable Memory Window
//
Register = 0x00000000;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);
Register = 0xffffffff;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);
//
// Program Memory Window to the PCI Root Bridge Memory Window
//
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);
//
// Enable the Memory decode for the PCI-PCI Bridge
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register |= 0x02;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
//
// Recurse on the Secondary Bus Number
//
ScanPciBus(
IoDev,
PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
CheckForRom, Context
);
}
} else {
//
// Check if an Option ROM Register is present and save the Option ROM Window Register
//
RomBar = 0xffffffff;
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
RomBarSize = (~(RomBar & 0xfffff800)) + 1;
//
// Make sure the size of the ROM is between 0 and 16 MB
//
if (RomBarSize > 0 && RomBarSize <= 0x01000000) {
//
// Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window
//
RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;
RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;
if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {
MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;
RomBar = RomBar + 1;
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
RomBar = RomBar - 1;
//
// Enable the Memory decode for the PCI Device
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register |= 0x02;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
//
// Follow the chain of images to determine the size of the Option ROM present
// Keep going until the last image is found by looking at the Indicator field
// or the size of an image is 0, or the size of all the images is bigger than the
// size of the window programmed into the PPB.
//
RomBarSize = 0;
do {
LastImage = TRUE;
ZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));
IoDev->Mem.Read (
IoDev,
EfiPciWidthUint8,
RomBar + RomBarSize,
sizeof(EfiRomHeader),
&EfiRomHeader
);
Pcir.ImageLength = 0;
if (EfiRomHeader.Signature == 0xaa55) {
ZeroMem (&Pcir, sizeof(Pcir));
IoDev->Mem.Read (
IoDev,
EfiPciWidthUint8,
RomBar + RomBarSize + EfiRomHeader.PcirOffset,
sizeof(Pcir),
&Pcir
);
if ((Pcir.Indicator & 0x80) == 0x00) {
LastImage = FALSE;
}
RomBarSize += Pcir.ImageLength * 512;
}
} while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);
if (RomBarSize > 0) {
//
// Allocate a memory buffer for the Option ROM contents.
//
Status = gBS->AllocatePages(
AllocateAnyPages,
EfiBootServicesData,
EFI_SIZE_TO_PAGES(RomBarSize),
&RomBuffer
);
if (!EFI_ERROR (Status)) {
//
// Copy the contents of the Option ROM to the memory buffer
//
IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);
Status = gBS->AllocatePool(
EfiBootServicesData,
((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),
&TempPciOptionRomDescriptors
);
if (mPciOptionRomTable.PciOptionRomCount > 0) {
CopyMem(
TempPciOptionRomDescriptors,
mPciOptionRomTable.PciOptionRomDescriptors,
(UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)
);
gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);
}
mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors;
TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);
TempPciOptionRomDescriptors->RomAddress = RomBuffer;
TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;
TempPciOptionRomDescriptors->RomLength = RomBarSize;
TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;
TempPciOptionRomDescriptors->Bus = (UINT8)Bus;
TempPciOptionRomDescriptors->Dev = (UINT8)Device;
TempPciOptionRomDescriptors->Func = (UINT8)Func;
TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;
TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;
mPciOptionRomTable.PciOptionRomCount++;
}
}
//
// Disable the Memory decode for the PCI-PCI Bridge
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register &= (~0x02);
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
}
}
}
//
// Restore the PCI Configuration Header
//
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
}
static
VOID
SaveCommandRegister (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
UINTN Index;
UINT16 Command;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
//
// Clear the memory enable bit
//
Command = Context->CommandRegisterBuffer[Index] & (~0x02);
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
}
static
VOID
RestoreCommandRegister (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
UINTN Index;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
}
EFI_STATUS
ScanPciRootBridgeForRoms(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
)
{
EFI_STATUS Status;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
UINT16 MinBus;
UINT16 MaxBus;
UINT64 RootWindowBase;
UINT64 RootWindowLimit;
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;
if (mPciOptionRomTableInstalled == FALSE) {
gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);
mPciOptionRomTableInstalled = TRUE;
}
Status = IoDev->Configuration(IoDev, &Descriptors);
if (EFI_ERROR (Status) || Descriptors == NULL) {
return EFI_NOT_FOUND;
}
MinBus = 0xffff;
MaxBus = 0xffff;
RootWindowBase = 0;
RootWindowLimit = 0;
while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
//
// Find bus range
//
if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
MinBus = (UINT16)Descriptors->AddrRangeMin;
MaxBus = (UINT16)Descriptors->AddrRangeMax;
}
//
// Find memory descriptors that are not prefetchable
//
if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {
//
// Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices
//
if (Descriptors->AddrRangeMax < 0x100000000) {
//
// Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB
//
if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {
RootWindowBase = Descriptors->AddrRangeMin;
RootWindowLimit = Descriptors->AddrRangeMax;
}
}
}
Descriptors ++;
}
//
// Make sure a bus range was found
//
if (MinBus == 0xffff || MaxBus == 0xffff) {
return EFI_NOT_FOUND;
}
//
// Make sure a non-prefetchable memory region was found
//
if (RootWindowBase == 0 && RootWindowLimit == 0) {
return EFI_NOT_FOUND;
}
//
// Round the Base and Limit values to 1 MB boudaries
//
RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;
RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;
//
// Make sure that the size of the rounded window is greater than zero
//
if (RootWindowLimit <= RootWindowBase) {
return EFI_NOT_FOUND;
}
//
// Allocate buffer to save the Command register from all the PCI devices
//
Context.CommandRegisterBuffer = NULL;
Status = gBS->AllocatePool(
EfiBootServicesData,
sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),
&Context.CommandRegisterBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);
//
// Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits
//
ScanPciBus(
IoDev,
MinBus, MaxBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
SaveCommandRegister, &Context
);
//
// Recursively scan all the busses for PCI Option ROMs
//
ScanPciBus(
IoDev,
MinBus, MinBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
CheckForRom, &Context
);
//
// Restore the Command register in all the PCI devices
//
ScanPciBus(
IoDev,
MinBus, MaxBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
RestoreCommandRegister, &Context
);
//
// Free the buffer used to save all the Command register values
//
gBS->FreePool(Context.CommandRegisterBuffer);
return EFI_SUCCESS;
}

View File

@ -0,0 +1,459 @@
/*++
Copyright (c) 2005, 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.
Module Name:
PcatPciRootBridgeIo.c
Abstract:
EFI PC AT PCI Root Bridge Io Protocol
Revision History
--*/
#include "PcatPciRootBridge.h"
#include "pci22.h"
#include "SalProc.h"
#include EFI_GUID_DEFINITION (SalSystemTable)
//
// Might be good to put this in an include file, but people may start
// using it! They should always access the EFI abstraction that is
// contained in this file. Just a little information hiding.
//
#define PORT_TO_MEM(_Port) ( ((_Port) & 0xffffffffffff0000) | (((_Port) & 0xfffc) << 10) | ((_Port) & 0x0fff) )
//
// Macro's with casts make this much easier to use and read.
//
#define PORT_TO_MEM8(_Port) (*(UINT8 *)(PORT_TO_MEM(_Port)))
#define PORT_TO_MEM16(_Port) (*(UINT16 *)(PORT_TO_MEM(_Port)))
#define PORT_TO_MEM32(_Port) (*(UINT32 *)(PORT_TO_MEM(_Port)))
#define EFI_PCI_ADDRESS_IA64(_seg, _bus,_dev,_func,_reg) \
( (UINT64) ( (((UINTN)_seg) << 24) + (((UINTN)_bus) << 16) + (((UINTN)_dev) << 11) + (((UINTN)_func) << 8) + ((UINTN)_reg)) )
//
// Local variables for performing SAL Proc calls
//
static PLABEL mSalProcPlabel;
static CALL_SAL_PROC mGlobalSalProc;
EFI_STATUS
PcatRootBridgeIoIoRead (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
UINTN InStride;
UINTN OutStride;
UINTN AlignMask;
UINTN Address;
PTR Buffer;
UINT16 Data16;
UINT32 Data32;
if ( UserBuffer == NULL ) {
return EFI_INVALID_PARAMETER;
}
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
Address = (UINTN) UserAddress;
Buffer.buf = (UINT8 *)UserBuffer;
if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
return EFI_INVALID_PARAMETER;
}
if (Width < 0 || Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
if ((Width & 0x03) == EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
AlignMask = (1 << (Width & 0x03)) - 1;
if ( Address & AlignMask ) {
return EFI_INVALID_PARAMETER;
}
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
InStride = 0;
}
if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
OutStride = 0;
}
Width = Width & 0x03;
Address += PrivateData->PhysicalIoBase;
//
// Loop for each iteration and move the data
//
switch (Width) {
case EfiPciWidthUint8:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
*Buffer.ui8 = PORT_TO_MEM8(Address);
MEMORY_FENCE();
}
break;
case EfiPciWidthUint16:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
if (Buffer.ui & 0x1) {
Data16 = PORT_TO_MEM16(Address);
*Buffer.ui8 = (UINT8)(Data16 & 0xff);
*(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff);
} else {
*Buffer.ui16 = PORT_TO_MEM16(Address);
}
MEMORY_FENCE();
}
break;
case EfiPciWidthUint32:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
if (Buffer.ui & 0x3) {
Data32 = PORT_TO_MEM32(Address);
*Buffer.ui8 = (UINT8)(Data32 & 0xff);
*(Buffer.ui8+1) = (UINT8)((Data32 >> 8) & 0xff);
*(Buffer.ui8+2) = (UINT8)((Data32 >> 16) & 0xff);
*(Buffer.ui8+3) = (UINT8)((Data32 >> 24) & 0xff);
} else {
*Buffer.ui32 = PORT_TO_MEM32(Address);
}
MEMORY_FENCE();
}
break;
}
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoIoWrite (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
UINTN InStride;
UINTN OutStride;
UINTN AlignMask;
UINTN Address;
PTR Buffer;
UINT16 Data16;
UINT32 Data32;
if ( UserBuffer == NULL ) {
return EFI_INVALID_PARAMETER;
}
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
Address = (UINTN) UserAddress;
Buffer.buf = (UINT8 *)UserBuffer;
if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
return EFI_INVALID_PARAMETER;
}
if (Width < 0 || Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
if ((Width & 0x03) == EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
AlignMask = (1 << (Width & 0x03)) - 1;
if ( Address & AlignMask ) {
return EFI_INVALID_PARAMETER;
}
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
InStride = 0;
}
if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
OutStride = 0;
}
Width = Width & 0x03;
Address += PrivateData->PhysicalIoBase;
//
// Loop for each iteration and move the data
//
switch (Width) {
case EfiPciWidthUint8:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
PORT_TO_MEM8(Address) = *Buffer.ui8;
MEMORY_FENCE();
}
break;
case EfiPciWidthUint16:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
if (Buffer.ui & 0x1) {
Data16 = *Buffer.ui8;
Data16 = Data16 | (*(Buffer.ui8+1) << 8);
PORT_TO_MEM16(Address) = Data16;
} else {
PORT_TO_MEM16(Address) = *Buffer.ui16;
}
MEMORY_FENCE();
}
break;
case EfiPciWidthUint32:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
if (Buffer.ui & 0x3) {
Data32 = *Buffer.ui8;
Data32 = Data32 | (*(Buffer.ui8+1) << 8);
Data32 = Data32 | (*(Buffer.ui8+2) << 16);
Data32 = Data32 | (*(Buffer.ui8+3) << 24);
PORT_TO_MEM32(Address) = Data32;
} else {
PORT_TO_MEM32(Address) = *Buffer.ui32;
}
MEMORY_FENCE();
}
break;
}
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoGetIoPortMapping (
OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
)
/*++
Get the IO Port Map from the SAL System Table.
--*/
{
SAL_SYSTEM_TABLE_ASCENDING_ORDER *SalSystemTable;
SAL_ST_MEMORY_DESCRIPTOR_ENTRY *SalMemDesc;
EFI_STATUS Status;
//
// On all Itanium architectures, bit 63 is the I/O bit for performming Memory Mapped I/O operations
//
*MemoryPortMapping = 0x8000000000000000;
Status = EfiLibGetSystemConfigurationTable(&gEfiSalSystemTableGuid, &SalSystemTable);
if (EFI_ERROR(Status)) {
return EFI_NOT_FOUND;
}
//
// BugBug: Add code to test checksum on the Sal System Table
//
if (SalSystemTable->Entry0.Type != 0) {
return EFI_UNSUPPORTED;
}
mSalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.SalProcEntry;
mSalProcPlabel.GP = SalSystemTable->Entry0.GlobalDataPointer;
mGlobalSalProc = (CALL_SAL_PROC)&mSalProcPlabel.ProcEntryPoint;
//
// The SalSystemTable pointer includes the Type 0 entry.
// The SalMemDesc is Type 1 so it comes next.
//
SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1);
while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) {
if (SalMemDesc->MemoryType == SAL_IO_PORT_MAPPING) {
*IoPortMapping = SalMemDesc->PhysicalMemoryAddress;
*IoPortMapping |= 0x8000000000000000;
return EFI_SUCCESS;
}
SalMemDesc++;
}
return EFI_UNSUPPORTED;
}
EFI_STATUS
PcatRootBridgeIoPciRW (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN BOOLEAN Write,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT UINT8 *UserBuffer
)
{
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
UINTN AlignMask;
UINTN InStride;
UINTN OutStride;
UINT64 Address;
DEFIO_PCI_ADDR *Defio;
PTR Buffer;
UINT32 Data32;
UINT16 Data16;
rArg Return;
if (Width < 0 || Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
if ((Width & 0x03) == EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
AlignMask = (1 << (Width & 0x03)) - 1;
if ( UserAddress & AlignMask ) {
return EFI_INVALID_PARAMETER;
}
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
InStride = 0;
}
if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
OutStride = 0;
}
Width = Width & 0x03;
Defio = (DEFIO_PCI_ADDR *)&UserAddress;
if ((Defio->Function > PCI_MAX_FUNC) || (Defio->Device > PCI_MAX_DEVICE)) {
return EFI_UNSUPPORTED;
}
Buffer.buf = (UINT8 *)UserBuffer;
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
Address = EFI_PCI_ADDRESS_IA64(
This->SegmentNumber,
Defio->Bus,
Defio->Device,
Defio->Function,
Defio->Register
);
//
// PCI Config access are all 32-bit alligned, but by accessing the
// CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
// are possible on PCI.
//
// SalProc takes care of reading the proper register depending on stride
//
EfiAcquireLock(&PrivateData->PciLock);
while (Count) {
if(Write) {
if (Buffer.ui & 0x3) {
Data32 = (*(Buffer.ui8+0) << 0);
Data32 |= (*(Buffer.ui8+1) << 8);
Data32 |= (*(Buffer.ui8+2) << 16);
Data32 |= (*(Buffer.ui8+3) << 24);
} else {
Data32 = *Buffer.ui32;
}
Return.p0 = -3;
Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_WRITE,
Address, 1 << Width, Data32, 0, 0, 0, 0);
if(Return.p0) {
EfiReleaseLock(&PrivateData->PciLock);
return EFI_UNSUPPORTED;
}
} else {
Return.p0 = -3;
Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_READ,
Address, 1 << Width, 0, 0, 0, 0, 0);
if(Return.p0) {
EfiReleaseLock(&PrivateData->PciLock);
return EFI_UNSUPPORTED;
}
switch (Width) {
case EfiPciWidthUint8:
*Buffer.ui8 = (UINT8)Return.p1;
break;
case EfiPciWidthUint16:
if (Buffer.ui & 0x1) {
Data16 = (UINT16)Return.p1;
*(Buffer.ui8 + 0) = Data16 & 0xff;
*(Buffer.ui8 + 1) = (Data16 >> 8) & 0xff;
} else {
*Buffer.ui16 = (UINT16)Return.p1;
}
break;
case EfiPciWidthUint32:
if (Buffer.ui & 0x3) {
Data32 = (UINT32)Return.p1;
*(Buffer.ui8 + 0) = (UINT8)(Data32 & 0xff);
*(Buffer.ui8 + 1) = (UINT8)((Data32 >> 8) & 0xff);
*(Buffer.ui8 + 2) = (UINT8)((Data32 >> 16) & 0xff);
*(Buffer.ui8 + 3) = (UINT8)((Data32 >> 24) & 0xff);
} else {
*Buffer.ui32 = (UINT32)Return.p1;
}
break;
}
}
Address += InStride;
Buffer.buf += OutStride;
Count -= 1;
}
EfiReleaseLock(&PrivateData->PciLock);
return EFI_SUCCESS;
}
EFI_STATUS
ScanPciRootBridgeForRoms(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
)
{
return EFI_UNSUPPORTED;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,215 @@
/*++
Copyright (c) 2005 - 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.
Module Name:
PcatPciRootBridge.h
Abstract:
The driver for the host to pci bridge (root bridge).
--*/
#ifndef _PCAT_PCI_ROOT_BRIDGE_H_
#define _PCAT_PCI_ROOT_BRIDGE_H_
#include <PiDxe.h>
#include <Protocol/PciRootBridgeIo.h>
#include <Protocol/DeviceIo.h>
#include <Protocol/CpuIo.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DevicePathLib.h>
#include <Library/HobLib.h>
#include <Guid/PciOptionRomTable.h>
#include <Guid/HobList.h>
#include <Guid/PciExpressBaseAddress.h>
#include <IndustryStandard/Acpi.h>
#include <IndustryStandard/Pci.h>
//
// Driver Instance Data Prototypes
//
#define PCAT_PCI_ROOT_BRIDGE_SIGNATURE EFI_SIGNATURE_32('p', 'c', 'r', 'b')
typedef struct {
UINT32 Signature;
EFI_HANDLE Handle;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
EFI_CPU_IO_PROTOCOL *CpuIo;
UINT32 RootBridgeNumber;
UINT32 PrimaryBus;
UINT32 SubordinateBus;
UINT64 MemBase; // Offsets host to bus memory addr.
UINT64 MemLimit; // Max allowable memory access
UINT64 IoBase; // Offsets host to bus io addr.
UINT64 IoLimit; // Max allowable io access
UINT64 PciAddress;
UINT64 PciData;
UINT64 PhysicalMemoryBase;
UINT64 PhysicalIoBase;
EFI_LOCK PciLock;
UINT64 Attributes;
UINT64 Mem32Base;
UINT64 Mem32Limit;
UINT64 Pmem32Base;
UINT64 Pmem32Limit;
UINT64 Mem64Base;
UINT64 Mem64Limit;
UINT64 Pmem64Base;
UINT64 Pmem64Limit;
UINT64 PciExpressBaseAddress;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
LIST_ENTRY MapInfo;
} PCAT_PCI_ROOT_BRIDGE_INSTANCE;
//
// Driver Instance Data Macros
//
#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \
CR(a, PCAT_PCI_ROOT_BRIDGE_INSTANCE, Io, PCAT_PCI_ROOT_BRIDGE_SIGNATURE)
#define VOLATILE volatile
//
// Private data types
//
typedef union {
UINT8 VOLATILE *buf;
UINT8 VOLATILE *ui8;
UINT16 VOLATILE *ui16;
UINT32 VOLATILE *ui32;
UINT64 VOLATILE *ui64;
UINTN VOLATILE ui;
} PTR;
typedef struct {
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation;
UINTN NumberOfBytes;
UINTN NumberOfPages;
EFI_PHYSICAL_ADDRESS HostAddress;
EFI_PHYSICAL_ADDRESS MappedHostAddress;
} MAP_INFO;
typedef struct {
LIST_ENTRY Link;
MAP_INFO * Map;
} MAP_INFO_INSTANCE;
typedef
VOID
(*EFI_PCI_BUS_SCAN_CALLBACK) (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *Context
);
typedef struct {
UINT16 *CommandRegisterBuffer;
UINT32 PpbMemoryWindow;
} PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT;
//
// Driver Protocol Constructor Prototypes
//
EFI_STATUS
ConstructConfiguration(
IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData
);
EFI_STATUS
PcatPciRootBridgeParseBars (
IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
IN UINT16 Command,
IN UINTN Bus,
IN UINTN Device,
IN UINTN Function
);
EFI_STATUS
ScanPciRootBridgeForRoms(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
);
EFI_STATUS
PcatRootBridgeDevicePathConstructor (
IN EFI_DEVICE_PATH_PROTOCOL **Protocol,
IN UINTN RootBridgeNumber,
IN BOOLEAN IsPciExpress
);
EFI_STATUS
PcatRootBridgeIoConstructor (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
IN UINTN SegmentNumber
);
EFI_STATUS
PcatRootBridgeIoGetIoPortMapping (
OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
);
EFI_STATUS
PcatRootBridgeIoPciRW (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN BOOLEAN Write,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
);
UINT64
GetPciExpressBaseAddressForRootBridge (
IN UINTN HostBridgeNumber,
IN UINTN RootBridgeNumber
);
//
// Driver entry point prototype
//
EFI_STATUS
EFIAPI
InitializePcatPciRootBridge (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
extern EFI_CPU_IO_PROTOCOL *gCpuIo;
#endif

View File

@ -0,0 +1,87 @@
/*++
Copyright (c) 2005 - 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.
Module Name:
PcatPciRootBridgeDevicePath.c
Abstract:
EFI PCAT PCI Root Bridge Device Path Protocol
Revision History
--*/
#include "PcatPciRootBridge.h"
//
// Static device path declarations for this driver.
//
typedef struct {
ACPI_HID_DEVICE_PATH AcpiDevicePath;
EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
static EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
{
ACPI_DEVICE_PATH,
ACPI_DP,
(UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
(UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8),
EISA_PNP_ID(0x0A03),
0
},
{
END_DEVICE_PATH_TYPE,
END_ENTIRE_DEVICE_PATH_SUBTYPE,
END_DEVICE_PATH_LENGTH,
0
}
};
EFI_STATUS
PcatRootBridgeDevicePathConstructor (
IN EFI_DEVICE_PATH_PROTOCOL **Protocol,
IN UINTN RootBridgeNumber,
IN BOOLEAN IsPciExpress
)
/*++
Routine Description:
Construct the device path protocol
Arguments:
Protocol - protocol to initialize
Returns:
None
--*/
{
ACPI_HID_DEVICE_PATH *AcpiDevicePath;
*Protocol = DuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL *)(&mEfiPciRootBridgeDevicePath));
AcpiDevicePath = (ACPI_HID_DEVICE_PATH *)(*Protocol);
AcpiDevicePath->UID = (UINT32)RootBridgeNumber;
if (IsPciExpress) {
AcpiDevicePath->HID = EISA_PNP_ID(0x0A08);
}
return EFI_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
#/*++
#
# Copyright (c) 2005 - 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.
#
# Module Name:
#
# Abstract:
#
#--*/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PcatPciRootBridge
FILE_GUID = 0F7EC77A-1EE1-400f-A99D-7CBD1FEB181E
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = InitializePcatPciRootBridge
[Packages]
MdePkg/MdePkg.dec
DuetPkg/DuetPkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
[LibraryClasses]
UefiDriverEntryPoint
UefiLib
MemoryAllocationLib
UefiBootServicesTableLib
DebugLib
BaseMemoryLib
DevicePathLib
HobLib
[Sources.common]
PcatPciRootBridge.h
PcatPciRootBridge.c
PcatPciRootBridgeDevicePath.c
PcatPciRootBridgeIo.c
DeviceIo.h
DeviceIo.c
[Sources.ia32]
ia32\PcatIo.c
[Sources.x64]
x64\PcatIo.c
[Sources.ipf]
Ipf\PcatIo.c
[Protocols]
gEfiPciRootBridgeIoProtocolGuid
gEfiDeviceIoProtocolGuid
gEfiPciExpressBaseAddressGuid
gEfiCpuIoProtocolGuid
[Guids]
gEfiPciOptionRomTableGuid

View File

@ -0,0 +1,732 @@
/*++
Copyright (c) 2005 - 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.
Module Name:
PcatPciRootBridgeIo.c
Abstract:
EFI PC AT PCI Root Bridge Io Protocol
Revision History
--*/
#include "PcatPciRootBridge.h"
static BOOLEAN mPciOptionRomTableInstalled = FALSE;
static EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};
EFI_STATUS
PcatRootBridgeIoIoRead (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
return gCpuIo->Io.Read (
gCpuIo,
(EFI_CPU_IO_PROTOCOL_WIDTH) Width,
UserAddress,
Count,
UserBuffer
);
}
EFI_STATUS
PcatRootBridgeIoIoWrite (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
return gCpuIo->Io.Write (
gCpuIo,
(EFI_CPU_IO_PROTOCOL_WIDTH) Width,
UserAddress,
Count,
UserBuffer
);
}
EFI_STATUS
PcatRootBridgeIoGetIoPortMapping (
OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
)
/*++
Get the IO Port Mapping. For IA-32 it is always 0.
--*/
{
*IoPortMapping = 0;
*MemoryPortMapping = 0;
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoPciRW (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN BOOLEAN Write,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
PCI_CONFIG_ACCESS_CF8 Pci;
PCI_CONFIG_ACCESS_CF8 PciAligned;
UINT32 InStride;
UINT32 OutStride;
UINTN PciData;
UINTN PciDataStride;
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
UINT64 PciExpressRegAddr;
BOOLEAN UsePciExpressAccess;
if (Width < 0 || Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
if ((Width & 0x03) >= EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
InStride = 0;
}
if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
OutStride = 0;
}
UsePciExpressAccess = FALSE;
EfiCopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
if (PciAddress.ExtendedRegister > 0xFF) {
//
// Check PciExpressBaseAddress
//
if ((PrivateData->PciExpressBaseAddress == 0) ||
(PrivateData->PciExpressBaseAddress >= EFI_MAX_ADDRESS)) {
return EFI_UNSUPPORTED;
} else {
UsePciExpressAccess = TRUE;
}
} else {
if (PciAddress.ExtendedRegister != 0) {
Pci.Reg = PciAddress.ExtendedRegister & 0xFF;
} else {
Pci.Reg = PciAddress.Register;
}
//
// Note: We can also use PciExpress access here, if wanted.
//
}
if (!UsePciExpressAccess) {
Pci.Func = PciAddress.Function;
Pci.Dev = PciAddress.Device;
Pci.Bus = PciAddress.Bus;
Pci.Reserved = 0;
Pci.Enable = 1;
//
// PCI Config access are all 32-bit alligned, but by accessing the
// CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
// are possible on PCI.
//
// To read a byte of PCI config space you load 0xcf8 and
// read 0xcfc, 0xcfd, 0xcfe, 0xcff
//
PciDataStride = Pci.Reg & 0x03;
while (Count) {
PciAligned = Pci;
PciAligned.Reg &= 0xfc;
PciData = (UINTN)PrivateData->PciData + PciDataStride;
EfiAcquireLock(&PrivateData->PciLock);
This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);
if (Write) {
This->Io.Write (This, Width, PciData, 1, UserBuffer);
} else {
This->Io.Read (This, Width, PciData, 1, UserBuffer);
}
EfiReleaseLock(&PrivateData->PciLock);
UserBuffer = ((UINT8 *)UserBuffer) + OutStride;
PciDataStride = (PciDataStride + InStride) % 4;
Pci.Reg += InStride;
Count -= 1;
}
} else {
//
// Access PCI-Express space by using memory mapped method.
//
PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |
(PciAddress.Bus << 20) |
(PciAddress.Device << 15) |
(PciAddress.Function << 12);
if (PciAddress.ExtendedRegister != 0) {
PciExpressRegAddr += PciAddress.ExtendedRegister;
} else {
PciExpressRegAddr += PciAddress.Register;
}
while (Count) {
if (Write) {
This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
} else {
This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
}
UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
PciExpressRegAddr += InStride;
Count -= 1;
}
}
return EFI_SUCCESS;
}
static
VOID
ScanPciBus(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
EFI_PCI_BUS_SCAN_CALLBACK Callback,
VOID *Context
)
{
UINT16 Bus;
UINT16 Device;
UINT16 Func;
UINT64 Address;
PCI_TYPE00 PciHeader;
//
// Loop through all busses
//
for (Bus = MinBus; Bus <= MaxBus; Bus++) {
//
// Loop 32 devices per bus
//
for (Device = MinDevice; Device <= MaxDevice; Device++) {
//
// Loop through 8 functions per device
//
for (Func = MinFunc; Func <= MaxFunc; Func++) {
//
// Compute the EFI Address required to access the PCI Configuration Header of this PCI Device
//
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
//
// Read the VendorID from this PCI Device's Confioguration Header
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);
//
// If VendorId = 0xffff, there does not exist a device at this
// location. For each device, if there is any function on it,
// there must be 1 function at Function 0. So if Func = 0, there
// will be no more functions in the same device, so we can break
// loop to deal with the next device.
//
if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {
break;
}
if (PciHeader.Hdr.VendorId != 0xffff) {
//
// Read the HeaderType to determine if this is a multi-function device
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);
//
// Call the callback function for the device that was found
//
Callback(
IoDev,
MinBus, MaxBus,
MinDevice, MaxDevice,
MinFunc, MaxFunc,
Bus,
Device,
Func,
Context
);
//
// If this is not a multi-function device, we can leave the loop
// to deal with the next device.
//
if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {
break;
}
}
}
}
}
}
static
VOID
CheckForRom (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
EFI_STATUS Status;
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
PCI_TYPE00 PciHeader;
PCI_TYPE01 *PciBridgeHeader;
UINT32 Register;
UINT32 RomBar;
UINT32 RomBarSize;
EFI_PHYSICAL_ADDRESS RomBuffer;
UINT32 MaxRomSize;
EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;
PCI_DATA_STRUCTURE Pcir;
EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;
BOOLEAN LastImage;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
//
// Save the contents of the PCI Configuration Header
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
if (IS_PCI_BRIDGE(&PciHeader)) {
PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);
//
// See if the PCI-PCI Bridge has its secondary interface enabled.
//
if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {
//
// Disable the Prefetchable Memory Window
//
Register = 0x00000000;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);
Register = 0xffffffff;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);
//
// Program Memory Window to the PCI Root Bridge Memory Window
//
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);
//
// Enable the Memory decode for the PCI-PCI Bridge
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register |= 0x02;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
//
// Recurse on the Secondary Bus Number
//
ScanPciBus(
IoDev,
PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
CheckForRom, Context
);
}
} else {
//
// Check if an Option ROM Register is present and save the Option ROM Window Register
//
RomBar = 0xffffffff;
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
RomBarSize = (~(RomBar & 0xfffff800)) + 1;
//
// Make sure the size of the ROM is between 0 and 16 MB
//
if (RomBarSize > 0 && RomBarSize <= 0x01000000) {
//
// Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window
//
RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;
RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;
if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {
MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;
RomBar = RomBar + 1;
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
RomBar = RomBar - 1;
//
// Enable the Memory decode for the PCI Device
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register |= 0x02;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
//
// Follow the chain of images to determine the size of the Option ROM present
// Keep going until the last image is found by looking at the Indicator field
// or the size of an image is 0, or the size of all the images is bigger than the
// size of the window programmed into the PPB.
//
RomBarSize = 0;
do {
LastImage = TRUE;
EfiZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));
IoDev->Mem.Read (
IoDev,
EfiPciWidthUint8,
RomBar + RomBarSize,
sizeof(EfiRomHeader),
&EfiRomHeader
);
Pcir.ImageLength = 0;
if (EfiRomHeader.Signature == 0xaa55) {
EfiZeroMem (&Pcir, sizeof(Pcir));
IoDev->Mem.Read (
IoDev,
EfiPciWidthUint8,
RomBar + RomBarSize + EfiRomHeader.PcirOffset,
sizeof(Pcir),
&Pcir
);
if ((Pcir.Indicator & 0x80) == 0x00) {
LastImage = FALSE;
}
RomBarSize += Pcir.ImageLength * 512;
}
} while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);
if (RomBarSize > 0) {
//
// Allocate a memory buffer for the Option ROM contents.
//
Status = gBS->AllocatePages(
AllocateAnyPages,
EfiBootServicesData,
EFI_SIZE_TO_PAGES(RomBarSize),
&RomBuffer
);
if (!EFI_ERROR (Status)) {
//
// Copy the contents of the Option ROM to the memory buffer
//
IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);
Status = gBS->AllocatePool(
EfiBootServicesData,
((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),
&TempPciOptionRomDescriptors
);
if (mPciOptionRomTable.PciOptionRomCount > 0) {
EfiCopyMem(
TempPciOptionRomDescriptors,
mPciOptionRomTable.PciOptionRomDescriptors,
(UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)
);
gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);
}
mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors;
TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);
TempPciOptionRomDescriptors->RomAddress = RomBuffer;
TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;
TempPciOptionRomDescriptors->RomLength = RomBarSize;
TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;
TempPciOptionRomDescriptors->Bus = (UINT8)Bus;
TempPciOptionRomDescriptors->Dev = (UINT8)Device;
TempPciOptionRomDescriptors->Func = (UINT8)Func;
TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;
TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;
mPciOptionRomTable.PciOptionRomCount++;
}
}
//
// Disable the Memory decode for the PCI-PCI Bridge
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register &= (~0x02);
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
}
}
}
//
// Restore the PCI Configuration Header
//
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
}
static
VOID
SaveCommandRegister (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
UINTN Index;
UINT16 Command;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
//
// Clear the memory enable bit
//
Command = Context->CommandRegisterBuffer[Index] & (~0x02);
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
}
static
VOID
RestoreCommandRegister (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
UINTN Index;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
}
EFI_STATUS
ScanPciRootBridgeForRoms(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
)
{
EFI_STATUS Status;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
UINT16 MinBus;
UINT16 MaxBus;
UINT64 RootWindowBase;
UINT64 RootWindowLimit;
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;
if (mPciOptionRomTableInstalled == FALSE) {
gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);
mPciOptionRomTableInstalled = TRUE;
}
Status = IoDev->Configuration(IoDev, &Descriptors);
if (EFI_ERROR (Status) || Descriptors == NULL) {
return EFI_NOT_FOUND;
}
MinBus = 0xffff;
MaxBus = 0xffff;
RootWindowBase = 0;
RootWindowLimit = 0;
while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
//
// Find bus range
//
if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
MinBus = (UINT16)Descriptors->AddrRangeMin;
MaxBus = (UINT16)Descriptors->AddrRangeMax;
}
//
// Find memory descriptors that are not prefetchable
//
if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {
//
// Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices
//
if (Descriptors->AddrRangeMax < 0x100000000) {
//
// Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB
//
if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {
RootWindowBase = Descriptors->AddrRangeMin;
RootWindowLimit = Descriptors->AddrRangeMax;
}
}
}
Descriptors ++;
}
//
// Make sure a bus range was found
//
if (MinBus == 0xffff || MaxBus == 0xffff) {
return EFI_NOT_FOUND;
}
//
// Make sure a non-prefetchable memory region was found
//
if (RootWindowBase == 0 && RootWindowLimit == 0) {
return EFI_NOT_FOUND;
}
//
// Round the Base and Limit values to 1 MB boudaries
//
RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;
RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;
//
// Make sure that the size of the rounded window is greater than zero
//
if (RootWindowLimit <= RootWindowBase) {
return EFI_NOT_FOUND;
}
//
// Allocate buffer to save the Command register from all the PCI devices
//
Context.CommandRegisterBuffer = NULL;
Status = gBS->AllocatePool(
EfiBootServicesData,
sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),
&Context.CommandRegisterBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);
//
// Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits
//
ScanPciBus(
IoDev,
MinBus, MaxBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
SaveCommandRegister, &Context
);
//
// Recursively scan all the busses for PCI Option ROMs
//
ScanPciBus(
IoDev,
MinBus, MinBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
CheckForRom, &Context
);
//
// Restore the Command register in all the PCI devices
//
ScanPciBus(
IoDev,
MinBus, MaxBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
RestoreCommandRegister, &Context
);
//
// Free the buffer used to save all the Command register values
//
gBS->FreePool(Context.CommandRegisterBuffer);
return EFI_SUCCESS;
}

View File

@ -0,0 +1,146 @@
/*++
Copyright (c) 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.
Module Name:
RtPlatformStatusCode.c
Abstract:
Contains NT32 specific implementations required to use status codes.
--*/
//
// Statements that include other files.
//
#include "Tiano.h"
#include "EfiCommonLib.h"
#include "EfiRuntimeLib.h"
#include "EfiStatusCode.h"
#include "EfiHobLib.h"
#include "RtMemoryStatusCodeLib.h"
#include "BsDataHubStatusCodeLib.h"
//
// Consumed protocols
//
#include EFI_ARCH_PROTOCOL_CONSUMER (StatusCode)
//
// GUID definitions
//
#include EFI_GUID_DEFINITION (Hob)
//
// Globals only work at BootService Time. NOT at Runtime!
//
EFI_REPORT_STATUS_CODE mPeiReportStatusCode;
//
// Function implementations
//
EFI_RUNTIMESERVICE
EFI_STATUS
EFIAPI
RtPlatformReportStatusCode (
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value,
IN UINT32 Instance,
IN EFI_GUID * CallerId,
IN EFI_STATUS_CODE_DATA * Data OPTIONAL
)
/*++
Routine Description:
Call all status code listeners in the MonoStatusCode.
Arguments:
Same as ReportStatusCode service
Returns:
EFI_SUCCESS Always returns success.
--*/
{
RtMemoryReportStatusCode (CodeType, Value, Instance, CallerId, Data);
if (EfiAtRuntime ()) {
//
// For now all we do is post code at runtime
//
return EFI_SUCCESS;
}
BsDataHubReportStatusCode (CodeType, Value, Instance, CallerId, Data);
//
// Call back into PEI to get status codes. This is because SecMain contains
// status code that reports to Win32.
//
if (mPeiReportStatusCode != NULL) {
return mPeiReportStatusCode (CodeType, Value, Instance, CallerId, Data);
}
return EFI_SUCCESS;
}
EFI_BOOTSERVICE
VOID
EFIAPI
RtPlatformInitializeStatusCode (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Initialize the status code listeners.
Arguments:
(Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
Returns:
None
--*/
{
EFI_STATUS Status;
VOID *HobList;
VOID *Pointer;
RtMemoryInitializeStatusCode (ImageHandle, SystemTable);
BsDataHubInitializeStatusCode (ImageHandle, SystemTable);
//
// Play any prior status codes to the data hub.
//
PlaybackStatusCodes (BsDataHubReportStatusCode);
//
// If PEI has a ReportStatusCode callback find it and use it before StdErr
// is connected.
//
mPeiReportStatusCode = NULL;
Status = EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
if (!EFI_ERROR (Status)) {
Status = GetNextGuidHob (&HobList, &gEfiStatusCodeRuntimeProtocolGuid, &Pointer, NULL);
if (!EFI_ERROR (Status)) {
mPeiReportStatusCode = (EFI_REPORT_STATUS_CODE) (*(UINTN *) Pointer);
}
}
}

View File

@ -0,0 +1,47 @@
#/*++
#
# Copyright (c) 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.
#
# Module Name:
#
# RtPlatformStatusCode.inf
#
# Abstract:
#
# Library selecting the listeners for the platform
#
#--*/
[defines]
BASE_NAME = RtPlatformStatusCodeLib
COMPONENT_TYPE = LIBRARY
[sources.common]
RtPlatformStatusCode.c
[includes.common]
$(EDK_SOURCE)\Foundation\Framework
$(EDK_SOURCE)\Foundation
$(EDK_SOURCE)\Foundation\Efi
.
$(EDK_SOURCE)\Sample\Platform\Generic\RuntimeDxe\StatusCode\Lib\Include
$(EDK_SOURCE)\Foundation\Include
$(EDK_SOURCE)\Foundation\Efi\Include
$(EDK_SOURCE)\Foundation\Framework\Include
$(EDK_SOURCE)\Foundation\Include\IndustryStandard
$(EDK_SOURCE)\Foundation\Core\Dxe
$(EDK_SOURCE)\Foundation\Library\Dxe\Include
[libraries.common]
HobLib
RtMemoryStatusCodeLib
BsDataHubStatusCodeLib
[nmake.common]