www.pudn.com > hpbios.rar > ACPI.ASM
; ; This source code is classified as confidential and ; contains trade secrets owned by Award Software, Inc. ; ; Copyright 1984, 1997 ; Award Software, Inc. ; All rights reserved. ; ; []==========================================================[] ;---------------------------------------------------------------------------- ;Rev Date Name Description ;---------------------------------------------------------------------------- ;OEM02 04/13/00 AVN Remove no use code, because we are always S3 support. ;OEM01 04/05/00 AVN Always support S1 + S3. ;R15a 03/02/00 JDN Supported MP STR. ;R15 02/18/00 TNY Always report S1 if MP-plugged. ;R14 02/15/00 DNL Added "Ct_Parse_AML" procedure to process AML code to ; support S1 or S3 dynamically ;R13 10/18/99 RTW Added Legacy free PC table entries ;R12 07/26/99 DNL Added APIC plamform MP support for Windows 2000 ;R11 09/19/98 TNY Always set "FACP_Pointer" to be public. ;R10 09/19/98 TNY Set "SetRealModeLimit" hook to be public. ;R09 04/02/98 DNL Fixed coding mistake ;---------------------------------------------------------------------------- PAGE 56,132 .386p include bios.cfg ifdef ACPI_Support include common.mac include acpi.inc include acpi_ct.inc include misc.equ extrn F000_Shadow_W:near extrn F000_Shadow_R:near extrn ACPITableAddress:near extrn ACPINVSAddress:near extrn A20_On:near extrn A20_Off:near ifdef Special_ACPI_Table_Update extrn Ct_ACPI_Table_Update:Near endif; Special_ACPI_Table_Update if CPU_THERMAL_SUPPORT EQ 1 extrn Ct_FillTempPointer:near endif ;CPU_THERMAL_SUPPORT EQ 1 ifdef MP_SUPPORT ;R12 extrn If_MP_PLUGGED:near ;R12 MPoffset = 38h ;R12 endif ;MP_SUPPORT ;R12 ;R14 - start ;OEM02 ifdef S3_SUPPORT ;OEM02 extrn F000_GetItem_Value:near ;OEM02 extrn Suspend_Mode_Item:near ;OEM02 endif ;S3_SUPPORT ;R14 - end CK_STRING_LENGTH MACRO SOFFSET IF2 IF ($ - SOFFSET NE 6) %OUT "ACPI_OEMID" IS A 6 BYTE STRING. !! .ERR ENDIF ENDIF ENDM DGROUP GROUP FCODE FCODE SEGMENT PARA PUBLIC 'CODE' ASSUME CS:DGROUP,DS:DGROUP ;----------------------------------------------------------------------- ;Build RSD PTR table ; ALIGN 16 Public RSD_PTR RSD_PTR: db "RSD PTR " ;RSD PTR Signature RSD_CKSM: db 0 ;Checksum, fill in at POST ACPIID_STR db ACPI_OEMID ; OEMID CK_STRING_LENGTHdb 0 ;Reserved RSDT_Ptr: db 4 dup (?) ;RSDT physical address, fill in at POST RSDPTRLength EQU ($-RSD_PTR) ;Total length of RSD_PTR table ;Keep the pointer for ACPI tables after move up to ACPI reclaim area ;so we don't have to scan for them again. These could be locate in E000. ;Since the code enable F000 shadow to writeable, it's just better to save them ;in F000 (only 16bytes) ;Note: The oder is important. It's one-to-one corresponding to ACPITables ; ALIGN 4 Public TempBuffArea TempBuffArea: RSDT_Pointer dd 0 ;Store RSDT pointer ;R11 ifdef Special_ACPI_Table_Update Public FACP_Pointer ;R11 endif; Special_ACPI_Table_Update FACP_Pointer dd 0 ;Store FACP pointer DSDT_Pointer dd 0 ;Store DSDT pointer ifdef SIMPLE_BOOT_SUPPORT ; BOOT_Pointer dd 0 ;Store BOOT pointer endif ;SIMPLE_BOOT_SUPPORT ; ifdef MP_SUPPORT ;R12 APIC_Pointer dd 0 ;R12 endif ;MP_SUPPORT ;R12 ifdef Debug_port_table ;R13 DBGP_Pointer dd 0 ;R13 store DBGP table pointer endif ;Debug_port_table ;R13 Public FACS_Pointer FACS_Pointer dd 0 ;Store FACS pointer FCODE ENDS ;-------------------------------------------------------------- ;----- The following codes will be located at E000 ! ---------- ;-------------------------------------------------------------- .386p EGROUP GROUP ECODE ECODE SEGMENT USE16 PARA PUBLIC 'ECODE' ASSUME CS:EGROUP, DS:NOTHING, ES:NOTHING ; include ACPI.INC RepMovsb32 Macro db 0f3h ;REP db 067h ;32bit addressing (ESI/EDI) db 0a4h ;MOVSB Endm ALIGN 4 extrn f000_call_proc:near Public ACPITables ACPITables: RSDT dd "TDSR" FACP dd "PCAF" DSDT dd "TDSD" ifdef SIMPLE_BOOT_SUPPORT BOOT dd "TOOB" endif ;SIMPLE_BOOT_SUPPORT ifdef MP_SUPPORT ;R12 APIC dd "CIPA" ;R12 endif ;MP_SUPPORT ;R12 ifdef Debug_port_table ;R13 DBGP dd "PGBD" ;R13 endif ; Debug_port_table ;R13 NoACPITables EQU ($ - offset ACPITables)/4 FACS dd "SCAF" ;[]========================================================================[] ; ; ; Entry: ; ; Exit: NONE ; ; Destroy : AX,DX ; ;[]========================================================================[] ;[]========================================================================[] ; SetupACPI ; ; Entry:After extended memory test, copy all ACPI tables to ACPI reclaim ; area (just below top of extended memory, see ATBASE INT15 function ; 0e820h). Then fill in physical address and checksum for all ACPI ; tables ; ; Exit: NONE ; ; Destory : All reserved ; ;[]========================================================================[] Public SetupACPI SetupACPI Proc Near push ds push es pushad mov al, 1 call SetRealModeLimit ;Enter big real mode F000_Call F000_Shadow_W ;Set F000 shadow to writeable call GetACPIReclaimArea ;Return EAX=physical address of ;reclaim memory area call MoveACPIToReclaim ;Move RSDT, FACP, DSDT tables to reclaim area call GetACPINVSArea ;Return EAX=physical address of ;ACPI NVS area call MoveACPItoNVS ;Move FACS table to NVS area. call FillACPIAddress ;Fill in the pointers for all tables ;R14 - start ifdef S3_SUPPORT Call Ct_Parse_AML endif ;S3_SUPPORT ;R14 - end ifdef Special_ACPI_Table_Update call Ct_ACPI_Table_Update endif; Special_ACPI_Table_Update call FillACPIChecksum ;Fill in check sum for all tables if CPU_THERMAL_SUPPORT EQ 1 call Ct_FillTempPointer endif ;CPU_THERMAL_SUPPORT EQ 1 F000_Call F000_Shadow_R ;Set F000 shadow to readable xor al, al ; call SetRealModelimit ;Leave big real mode NoACPITable: popad pop es pop ds ret SetupACPI Endp ;[]========================================================================[] ; SearchACPITables ; Search ACPI table and return physical address ; Entry:EAX = ACPI table signature e.g "RSDT" ; EBX = Start physical address ; EDX = End physical address ; Exit: ESI = Physical address of table found ; NC = ACPI table found ; CY = Error, ACPI table not found ; ; Destroy : ESI ; ;[]========================================================================[] SearchACPITables Proc Near clc ;clear the flag mov esi, ebx ;start from here SearchACPILoop: cmp dword ptr ds:[esi], eax ;ACPI table? je short @f ;Found it, inc esi ;Next byte cmp esi, edx ;Reach the end? jb SearchACPILoop stc jmp SearchACPIExit ;Set CF and jump out @@: clc SearchACPIExit: ret SearchACPITables Endp ;[]========================================================================[] ; GetACPIReclaimArea ; Return starting physical address of ACPI reclaim area ; Entry: NONE ; ; Exit: EAX ; ; Destroy : EAX ; ;[]========================================================================[] GetACPIReclaimArea Proc Near push ds mov ax, 0f000h mov ds, ax mov eax, dword ptr ds:[ACPITableAddress] and eax,not 0ffh ;clear end maker pop ds ret GetACPIReclaimArea Endp ;[]========================================================================[] ; GetACPINVSArea ; Return starting physical address of ACPI NVS area ; Entry: NONE ; ; Exit: EAX ; ; Destroy : EAX ; ;[]========================================================================[] GetACPINVSArea Proc Near push ds mov ax, 0f000h mov ds, ax mov eax, dword ptr ds:[ACPINVSAddress] and eax,not 0ffh ;clear end maker pop ds ret GetACPINVSArea Endp ;[]========================================================================[] ; MoveACPIToReclaim ; Move copies of ACPI tables from somewhere below 1Mb to top of extended ; memory. Looping from source starting address, look for valid header signature ; Get the length at byte offset 4, and move the each table up one by one. ; RSDT is the first table to look for (see ACPITables.) ; Entry: EAX = ACPI reclaim memory destination ; Exit: None ; Destroy : None ; ;[]========================================================================[] Public MoveACPIToReclaim MoveACPIToReclaim Proc Near push eax push cx push ebp xor ebp, ebp mov cx, NoACPITables ;Get total number of tables mov edi, eax ;Get ACPI reclaim address MoveAnother: mov eax, dword ptr cs:[ACPITables+bp];Get table signature mov ebx, ACPISearchStart ;Look from here mov edx, ACPISearchEnd ;To here call SearchACPITables ;Return ESI jc short NotFound ;DSDT table need to be 64 byte aligned. ;Just align all table to make it easier. test di, 03fh ;aligned? jz short @f ;Yes, jump over add edi, 40h ; and di, 0ffc0h ;Make it align @@: push esi ;Need to use ESI for awhile mov esi, ACPISeg ;Save current ACPI pointer or esi, offset TempBuffArea add esi, ebp ;Get buffer pointer mov dword ptr ds:[esi], edi ;Save ACPI pointer pop esi ;Get ESI=source pointer call MoveTables ;Use current ESI and EDI NotFound: add bp, 4 ;Add pointer to next table loop MoveAnother ;Loop until end pop ebp pop cx pop eax ret MoveACPIToReclaim Endp ;[]========================================================================[] ; MoveACPIToNVS ; Move copies of ACPI tables from somewhere below 1Mb to top of extended ; memory. Looping from source starting address, look for valid header signature ; Get the length at byte offset 4, and move the each table up one by one. ; RSDT is the first table to look for (see ACPITables.) ; Entry: EAX = ACPI reclaim memory destination ; Exit: None ; Destroy : None ; ;[]========================================================================[] Public MoveACPIToNVS MoveACPIToNVS Proc Near push eax mov edi, eax ;Get ACPI reclaim address mov eax, FACS mov ebx, ACPISearchStart ;Look from here mov edx, ACPISearchEnd ;To here call SearchACPITables ;Return ESI jc short FACSNotFound push esi ;Need to use ESI for awhile mov esi, ACPISeg ;Save current ACPI pointer or esi, offset FACS_Pointer mov dword ptr ds:[esi], edi ;Save ACPI pointer pop esi ;Get ESI=source pointer call MoveTables ;Use current ESI and EDI FACSNotFound: pop eax ret MoveACPItoNVS Endp ;[]========================================================================[] ; MoveTables ; Similiar to REP MOVSB, but works with 32 bits ESI and EDI ; ; Entry:ESI = source starting physical address ; EDI = destination starting physical address ; Exit: NONE ; Destroy : ESI, EDI ; ;[]========================================================================[] Public MoveTables MoveTables Proc Near push ecx cld mov ecx, dword ptr ds:[esi]+LengthOffset RepMovsb32 pop ecx ret MoveTables Endp ;[]========================================================================[] ; FillACPIAddress ; For each ACPI table, fill in the pointer of other table. ; e.g RSDT needs a pointer to FACP. FACP needs a pointer to FACS and DSDT ; Entry: Pointers are saved in TempBuffArea ; ; Exit: None ; ; Destroy : None ; ;[]========================================================================[] FillACPIAddress Proc Near push edi push esi mov esi, ACPISeg ;RSD_PTR table need RSDT pointer ; mov eax, dword ptr ds:[esi]+offset RSDT_Pointer ;RSD_PTR or eax, eax jz FillExit mov dword ptr ds:[esi]+offset RSDT_Ptr, eax ; ;FACP table need FACS and DSDT pointers ; mov eax, dword ptr ds:[esi]+offset DSDT_Pointer ; or eax, eax jz FillExit mov edi, dword ptr ds:[esi]+offset FACP_Pointer ;FACP mov dword ptr es:[edi]+DSDTOffset, eax ; mov eax, dword ptr ds:[esi]+offset FACS_Pointer ; or eax, eax jz FillExit mov edi, dword ptr ds:[esi]+offset FACP_Pointer ;FACP mov dword ptr es:[edi]+FACSOffset, eax ; ;RSDT table need FACP pointers ; mov eax, dword ptr ds:[esi]+offset FACP_Pointer ; or eax, eax jz FillExit mov edi, dword ptr ds:[esi]+offset RSDT_Pointer ;RSDT mov dword ptr es:[edi]+FACPOffset, eax ; ifdef SIMPLE_BOOT_SUPPORT mov eax, dword ptr ds:[esi]+offset BOOT_Pointer ; or eax, eax jz short @F mov edi, dword ptr ds:[esi]+offset RSDT_Pointer ;RSDT mov dword ptr es:[edi]+BOOTOffset, eax ; @@: endif ;SIMPLE_BOOT_SUPPORT ;R12 - start ifdef MP_SUPPORT mov eax, dword ptr ds:[esi]+offset APIC_Pointer ; or eax, eax jz short @F mov edi, dword ptr ds:[esi]+offset RSDT_Pointer ;RSDT mov dword ptr es:[edi]+APICOffset, eax ; mov edi,eax push es Call If_MP_PLUGGED pop es jnc short @f and dword ptr es:[edi]+MPOffset, Not 01h @@: endif ;MP_SUPPORT ;R12 - end ;R13 -start ifdef Debug_port_table mov eax, dword ptr ds:[esi]+offset DBGP_Pointer ; or eax, eax jz short @F mov edi, dword ptr ds:[esi]+offset RSDT_Pointer ;RSDT mov dword ptr es:[edi]+DBGPOffset, eax ; @@: endif ;Debug_port_table ;R13 -end FillExit: pop esi pop edi ret FillACPIAddress Endp ;[]========================================================================[] ; FillACPIChecksum ; For each ACPI table, caculate the checksum of entire table and fill in ; according to table type (RSD_PTR is different with the rest) ; ; Entry: ; ; Exit: None ; ; Destroy : None ; ;[]========================================================================[] FillACPIChecksum Proc Near push ax push cx push esi push ebp xor ecx, ecx xor ebp, ebp ;Do RSD_PTR checksum first because it's different than others ; mov esi, ACPISeg or esi, offset RSD_PTR mov cl, RSDPTRLength xor al, al ;Zero out checksum byte first mov byte ptr ds:[esi]+RSDPTRChksumOffset, al call GetCheckSum mov byte ptr ds:[esi]+RSDPTRChksumOffset, al ;Other ACPI tables checksum ; xor ecx, ecx mov cl, NoACPITables ChksumAgain: push ecx ;Save number of tables to do checksum mov esi, ACPISeg or esi, offset TempBuffArea add esi, ebp mov esi, dword ptr ds:[esi] ;Get start address mov ecx, dword ptr ds:[esi]+LengthOffset ;Get total length xor al, al ;Zero out checksum byte first mov byte ptr ds:[esi]+ChksumOffset, al ; call GetCheckSum mov byte ptr ds:[esi]+ChksumOffset, al ;Fill checksum for this table SkipChecksum: pop ecx add bp, 4 ;Next table loop ChksumAgain pop ebp pop esi pop cx pop ax ret FillACPIChecksum Endp ;[]========================================================================[] ; GetCheckSum ; Calculate the checksum for a block of data ; ; Entry: ECX =Length ; ESI=Start physical address of block to do checksum ; Exit: AL =checksum byte ; ; Destroy : AX ; ;[]========================================================================[] GetCheckSum Proc Near push ecx push esi xor al, al chkSumLoop: add al, byte ptr ds:[esi] ; get a byte and add it inc esi ; Update pointer loop chkSumLoop ; Loop till done neg al ; Make zero compliment pop esi pop ecx ret GetCheckSum Endp ;[]========================================================================[] ; SetRealModeLimit ; Setup ES and DS segment limit for real mode ; Entry:AL=1 ES and DS will set to 4Gb segment limit ; AL=0 ES and DS will set back to 64Kb segment limit ; ; Exit: NONE ; ; Destroy : ES, DS ; ;[]========================================================================[] public SetRealModeLimit ;R10 SetRealModeLimit Proc Near push eax or al, al ;Set up as 64Kb limit? jz short @f ; F000_call A20_On ;enable A20 for 4Gb limit jmp short Enable4Gb @@: F000_call A20_Off ;disable A20 for 64Kb limit Enable4Gb: mov ax,cs mov es,ax lea di, GDTR cli ;clear interrupt lgdt fword ptr es:[di] ;Load Global Descriptor Table mov eax,cr0 or al,1 mov cr0,eax ;Enter protected mode jmp @f ;jump to clear CPU instruction queue @@: pop eax ;Get AL push eax ;Save EAX again or al, al ;Set up as 64Kb limit? jz short @f ; mov ax, DATA4G_INDEX ;No, set DS, ES to 4Gb limit jmp short Enable4Gb_ @@: mov ax, DATA64K_INDEX ;Set DS, ES back to 64kb limit Enable4GB_: mov es,ax ; mov ds,ax ;Switch back to real mode, DS and ES limits are set ; mov eax,cr0 and al,NOT 1 mov cr0,eax jmp @f ; clear prefetch queue. @@: xor ax, ax mov ds, ax ;DS and ES limit are set mov es, ax pop eax ret SetRealModeLimit Endp ALIGN 4 GDTR: ; global descriptor table register dw 8*3 ; LIMIT dw offset GDT1 dw 0eh ; in 0e000h segment GDT1: ; null descriptor dw 0 ; limit dw 0 ; base db 0 ; hibase db 0 ; access db 0 ; hilimit db 0 ; msbase DATA64K: ; cs - prom code segment DATA64K_INDEX = ((offset DATA64K - offset GDT1)/8) SHL 3 dw 0ffffh ; limit dw 0 ; base db 0 ; hibase db 93h ; access db 0 ; hilimit db 0 ; msbase DATA4G: DATA4G_INDEX = ((OFFSET DATA4G - OFFSET GDT1)/8) SHL 3 dw 0ffffh ; limit dw 0 ; base data segment points to db 0 ; hibase ; 00000000 db 93h ; access db 08fh ; hilimit (4GB) db 0 ; msbase ;R14 - start ifdef S3_SUPPORT Ct_PARSE_AML Proc near ;OEM01 mov si,offset DGROUP:Suspend_Mode_Item ;OEM01 call F000_GetItem_Value ;OEM01 or al,al ;S1? ;OEM01 jz short No_Change ;Yes ;OEM01 ;OEM01 ;R15 - start ;OEM01 ;R15aifdef MP_SUPPORT ;OEM01 ;R15a ;If MP-plugged , plways report S1 only. ;OEM01 ;R15a push es ;OEM01 ;R15a Call If_MP_PLUGGED ;OEM01 ;R15a pop es ;OEM01 ;R15a jnc No_Change ;OEM01 ;R15aendif; MP_SUPPORT ;OEM01 ;R15 - end ;OEM01 ;OEM01 mov esi, ACPISeg ;OEM01 mov esi, dword ptr ds:[esi] + offset DSDT_Pointer ;OEM01 mov edi, esi ;OEM01 mov cx , ds:[esi+4] ; Get AML code size ;OEM01 sub cx, 24h ;OEM01 add esi, 24h ;OEM01 mov eax, "_1S_" ;OEM01 @@: ;OEM01 cmp eax, ds:[esi] ;OEM01 je short Get_S1 ;OEM01 inc esi ;OEM01 loop short @B ;OEM01 ;OEM01 jmp short No_Change ;OEM01 Get_S1: ;OEM01 mov bh, ds:[edi+9] ; Get AML code checksum ;OEM01 add bh, ds:[esi+2] ;OEM01 add bh, ds:[esi+8] ;OEM01 ;OEM01 mov dword ptr ds:[esi], "_3S_" ;OEM01 mov bl,(S3 shr 2) ;OEM01 mov ds:[esi+8], bl ;OEM01 add bl, ds:[esi+2] ;OEM01 sub bh, bl ;OEM01 mov ds:[edi+9],bh ; Update AML code checksum ;OEM01 No_Change: ret Ct_PARSE_AML Endp endif ;S3_SUPPORT ;R14 - end ECODE ENDS ;-------------------------------------------------------------------------- ; endif; ACPI_Support END