summaryrefslogtreecommitdiff
path: root/cpu/amd/geode_lx/gplvsa_ii/sysmgr/init.asm
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/amd/geode_lx/gplvsa_ii/sysmgr/init.asm')
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/init.asm1017
1 files changed, 1017 insertions, 0 deletions
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/init.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/init.asm
new file mode 100755
index 0000000..34b6742
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/init.asm
@@ -0,0 +1,1017 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;*******************************************************************************
+;* This file contains the installation code for VSA II.
+;*
+;* BIOS Usage:
+;* CALL far ptr [VSA_Entry]
+;* where VSA_Entry: dw 0020h, <segment>
+;*
+;*******************************************************************************
+
+
+include vsa2.inc
+include sysmgr.inc
+include init.inc
+include smimac.mac
+include chipset.inc
+;include vpci.inc
+DESCRIPTOR struc
+DescrType BYTE ? ; Type of MSR
+Flag BYTE ? ; See definitions below
+Link BYTE ? ; Link to next MSR
+Split BYTE ? ; Index of descriptor that was split
+
+Owner WORD ? ; PCI Address this descriptor belongs to
+Mbiu BYTE ? ; MBUI on which this descriptor is located
+Port BYTE ? ; Port this descriptor routes to
+
+MsrAddr DWORD ? ; Routing address of MSR (descriptor/LBAR/RCONF)
+MsrData0 DWORD ? ; MSR data low
+MsrData1 DWORD ? ; MSR data high
+Physical DWORD ? ; Physical memory assigned (00000000 if none)
+Range DWORD ? ; Actual I/O range for IOD_SC
+Address WORD ? ; Address of I/O Trap or Timeout
+DESCRIPTOR ENDS
+
+
+.model small,c
+.586
+.CODE
+
+VERIFY_VSM_COPY equ 1 ; 0=skip verify
+
+
+SW_SMI equ 0D0h
+
+
+; VSA loader debug codes:
+VSA_ENTERED equ 10h ; VSA installation has been entered
+VSA_INIT1 equ 11h ; Returned from Setup
+VSA_SYSMGR equ 12h ; Image of SysMgr was found
+VSA_VSM_FOUND equ 13h ; A VSM has been found (followed by VSM type)
+VSA_COPY_START equ 14h ; Start of module copy
+VSA_COPY_END equ 15h ; End of module copy
+VSA_VRFY_START equ 1Ch ; Start of verifying module copy
+VSA_VRFY_END equ 1Dh ; End of verifying module copy
+VSA_FILL_START equ 1Eh ; Start of filling BSS
+VSA_FILL_END equ 1Fh ; End of filling BSS
+VSA_INIT2 equ 16h ; Returned from copying VSA image
+VSA_INIT3 equ 17h ; Performing VSA initialization SMI
+VSA_INIT4 equ 18h ; Returned from s/w SMI
+VSA_INIT5 equ 19h ; Returned from initializing statistics
+VSA_INIT6 equ 1Ah ; Returning to BIOS
+VSA_ERROR equ 0EEh ; Installation error. EBX contains error mask
+
+
+
+; NOTES:
+; 1) A VSM's CS segment must be writeable since the message queue is
+; stored there and the VSM must be able to update the pointers.
+; 2) The nested flag must be set so when the System Manager RSMs
+; to a VSM, the processor remains in SMM.
+VSM_FLAGS equ SMI_FLAGS_CS_WRITABLE + SMI_FLAGS_NESTED + SMI_FLAGS_CS_READABLE
+
+
+
+
+
+POST macro Code
+
+ mov al, Code
+ out 80h, al
+
+ endm
+
+public Device_ID
+public Chipset_Base
+public Errors
+public BIOS_ECX
+public BIOS_EDX
+
+
+externdef Software_SMI: proc
+externdef Get_Sbridge_Info: proc
+externdef Get_IRQ_Base: proc
+externdef Get_SMI_Base: proc
+externdef Get_CPU_Info: proc
+externdef Clear_SMIs: proc
+externdef Get_SMM_Region: proc
+externdef Init_SMM_Region: proc
+externdef Enable_SMIs: proc
+externdef Enable_SMM_Instr: proc
+externdef Disable_A20: proc
+externdef Get_Memory_Size: proc
+externdef Set_CPU_Fields: proc
+externdef VSA_Image: byte
+
+
+
+
+ ORG 0000h
+;***********************************************************************
+; Entry Point for DOS installer
+;***********************************************************************
+VSA_Installation:
+
+ mov dx, offset Msg_Not_DOS_BUILD
+ push cs ; DS <= CS
+ pop ds
+ mov ah, 9 ; Call DOS PrintString
+ int 21h
+
+
+ReturnToDOS:
+ sti
+ mov ah, 4Ch ; Return to DOS
+ int 21h
+
+
+ org 001Eh ; Used by INFO to skip over init code
+ dw offset VSA_Image
+
+
+;***********************************************************************
+; Entry point for BIOS installer
+;***********************************************************************
+ org 0020h
+
+VSA_Install proc far
+
+ POST VSA_ENTERED
+
+ pushf
+ push cs ; DS <- CS
+ pop ds
+ ASSUME DS:_TEXT
+ mov [BIOS_ECX], ecx ; MSR address of SMM memory descriptor (P2D_BMO)
+ mov [BIOS_EDX], edx ; MSR address of system memory descriptor (P2D_R)
+
+
+;
+; Make sure VSM's SmiHeader is DWORD aligned
+;
+ mov si, VSM_Header.SysStuff.State
+ test si, 3
+ jz AlignmentOK
+ mov bx, [Errors]
+ or bx, ERR_INTERNAL
+ jmp DisplayErrors
+
+AlignmentOK:
+
+
+ ; Set up for SMM
+ call Setup
+ jc DisplayErrors
+
+ ; Load System Manager and VSMs into memory
+ POST VSA_INIT1
+ call ProcessModules
+ POST VSA_INIT2
+
+ push cs
+ pop ds
+
+ mov bx, [Errors] ; Any errors detected ?
+ test bx, bx
+ jz Init_VSA
+DisplayErrors:
+ POST VSA_ERROR
+
+ jmp Exit
+
+
+Init_VSA:
+ cli
+
+ ; Set SMM MSRs
+ mov ebx, [SysMgrEntry]
+ call Init_SMM_Region
+
+
+ ; Generate s/w SMI to initialize VSA
+ POST VSA_INIT3 ; POST 17h
+
+
+ call Enable_SMIs ; Enable SMIs
+ movzx eax, [SysCall_Code]
+ mov ebx, [InitParam1]
+ mov ecx, [InitParam2]
+ call Software_SMI
+
+ POST VSA_INIT4 ; POST 18h
+
+
+ call InitStatistics ; Initialize VSA statistics
+
+ POST VSA_INIT5 ; POST 19h
+
+
+Exit:
+ POST VSA_INIT6 ; POST 1Ah
+ popf
+ ret
+
+VSA_Install endp
+
+ ASSUME DS:NOTHING
+
+
+;***********************************************************************
+;***********************************************************************
+;***********************************************************************
+;***********************************************************************
+
+
+
+
+
+;***********************************************************************
+;
+; Some of the time in SMM cannot be recorded by VSA.
+; This unaccounted time consists of:
+; 1) the cycles used to write the SMM header.
+; 2) the cycles for the SMM entry code before RDTSC is executed.
+; 3) the cycles between the exit RDTSC through the RSM instruction.
+;
+; The following code calculates how many clocks this time consists
+; of and stores it in a VSA structure. It is used as an adjustment
+; to the statistics calculations.
+;
+;***********************************************************************
+InitStatistics proc
+
+ in al, 92h ; Save A20 mask
+ push ax
+
+ mov si, 0 ; Don't toggle A20 (no SMI)
+ call DeltaSMI
+ mov edi, eax ; EDI = overhead of DeltaSMI()
+
+ mov ebx, [SysMgrEntry] ; Get ptr to SysMgr's header
+ add ebx, VSM_Header.SysStuff
+ mov es:(System PTR [ebx]).Clocks, 0
+ mov si, 2 ; Generate an SMI by toggling A20
+ call DeltaSMI
+
+ mov ecx, es:(System PTR [ebx]).Clocks
+ sub eax, ecx ; Subtract clocks VSA determined
+ sub eax, edi ; Subtract DeltaSMI() overhead
+ mov es:(System PTR [ebx]).Adjustment, eax
+
+ pop ax ; Restore A20 mask
+ out 92h, al
+
+ ; Initialize statistics structure
+ RDTSC ; Record VSA start time
+ mov es:(System PTR [ebx+0]).StartClocks, eax
+ mov es:(System PTR [ebx+4]).StartClocks, edx
+ xor eax, eax
+ mov es:(System PTR [ebx+0]).Clocks, eax
+ mov es:(System PTR [ebx+4]).Clocks, eax
+ mov es:(System PTR [ebx+0]).NumSMIs, eax
+ mov es:(System PTR [ebx+4]).NumSMIs, eax
+ ret
+
+InitStatistics endp
+
+;***********************************************************************
+; Helper routine for InitStatistics()
+; Input: SI = XOR mask for port 92h
+;***********************************************************************
+DeltaSMI proc
+
+ RDTSC ; Record VSA start time
+ mov ecx, eax
+
+ in al, 92h ; Generate an SMI by toggling A20 mask
+ xor ax, si
+ out 92h, al
+
+ RDTSC ; Compute actual delta clocks
+ sub eax, ecx
+ jnc Exit
+ neg eax ; TSC rolled over
+Exit: ret
+
+DeltaSMI endp
+
+
+
+
+;***********************************************************************
+; Setup for VSA installation:
+; - Gets information about the system: CPU, Southbridge, memory, PCI
+; - Sets ES to be 4 GB descriptor
+; - Clears pending SMIs
+;***********************************************************************
+Setup proc near
+
+ ASSUME DS:_TEXT
+
+ cli
+
+ call Get_CPU_Info ; Get information about the CPU
+ mov [Cpu_Revision], ax
+ mov [Cpu_ID], si
+ mov [PCI_MHz], bx
+ mov [CPU_MHz], cx
+ mov [DRAM_MHz], dx
+
+ call Get_Sbridge_Info ; Get information about the Southbridge
+ jc short SetupExit
+ mov [Chipset_Base], ebx
+ mov [Device_ID], dx
+ mov [Chipset_Rev], cl
+
+ call Get_SMM_Region ; Get SMM entry point
+ mov [ModuleBase], eax
+ mov [SysMgr_Location], eax
+ mov [VSA_Size], bx
+ movzx ebx, bx ; Get end of VSA memory
+ shl ebx, 10
+ add eax, ebx
+ mov [VSA_End], eax
+
+ call Enable_SMM_Instr ; Enable SMM instructions
+
+
+ rsdc es, [Flat_Descriptor] ; Setup ES as a 4 GB flat descriptor
+
+
+ call Disable_A20 ; Turn off A20 masking
+
+
+ call Get_Memory_Size ; Get physical memory size
+ mov [TotalMemory], eax
+
+
+ call Clear_SMIs ; Clear all pending SMIs
+
+SetupExit:
+ mov [SetupComplete], 0FFh
+ clc
+ ret
+
+
+ ASSUME DS: NOTHING
+
+Setup endp
+
+
+
+
+
+
+
+
+
+
+
+;*****************************************************************************
+;
+; Loads the VSA II image into memory
+; NOTE: The System Manager must be the first module of the VSA image.
+;
+;*****************************************************************************
+ProcessModules proc
+
+ ; Point DS:ESI to loaded VSA image
+ lea bx, [VSA_Image] ; Point DS to start of file image
+ movzx esi, bx
+ and si, 000Fh
+ shr bx, 4
+ mov ax, cs
+ add ax, bx
+ mov ds, ax
+
+ ; Point EDI to where System Manager will be loaded
+ mov edi, cs:[ModuleBase] ; Get last ptr value
+ call AlignVSM
+ mov cs:[SysMgrEntry], edi ; Record entry point of System Manager
+
+
+ ; Ensure the System Manager is the first module unless loading from DOS
+ mov ax, ERR_NO_SYS_MGR
+ cmp (VSM_Header PTR [si]).Signature, VSM_SIGNATURE
+ jne ErrExit
+ cmp (VSM_Header PTR [si]).VSM_Type, VSM_SYS_MGR
+ je LoadSysMgr
+
+
+LoadSysMgr:
+ POST VSA_SYSMGR
+ call PatchSysMgr ; Apply patches to the System Manager
+
+ ; EDI = flat ptr of System Manager base
+ ; DS:SI = near ptr to System Manager image
+ call CopyModule ; Install System Manager
+ jc ErrExit
+
+
+
+ ; Sequence through each VSM and install it.
+VSM_Loop:
+ mov eax, VSM_SIGNATURE ; Check for a VSM signature
+ cmp eax, (VSM_Header PTR [si]).Signature
+ jne short Return
+ call Load_VSM ; Load the VSM
+ jnc VSM_Loop
+
+
+ErrExit:or cs:[Errors], ax
+Return: ret
+
+ProcessModules endp
+
+
+
+
+
+
+;*****************************************************************************
+; Copies INT vector table to VSA. If installing VSA from DOS, copies the
+; INT_Vector[] from current System Manager to the VSA image being installed.
+;*****************************************************************************
+SnagInterruptVectors proc
+
+Exit: ret
+
+SnagInterruptVectors endp
+
+
+
+
+
+
+;*******************************************************************
+;
+; Aligns a VSM ptr according to requirements flag
+; Input:
+; EDI = ptr to be aligned
+; Output:
+; EDI = aligned ptr
+;
+;*******************************************************************
+AlignVSM proc uses eax
+
+ mov cx, cs:[Requirments] ; Compute alignment
+ and cl, MASK Alignment@@tag_i0 ; Compute mask from 2^(n+4)
+ add cl, 4
+ xor eax, eax
+ mov al, 1
+ shl eax, cl
+ dec eax
+
+ add edi, eax ; Align the next VSM load address
+ not eax ; to requested boundary
+ and edi, eax
+ ret
+
+AlignVSM endp
+
+
+
+
+;*******************************************************************
+; Patches various fields within System Manager
+; INPUT:
+; SI = ptr to System Manager
+; EDI = ptr to where System Manager will reside
+;*******************************************************************
+PatchSysMgr proc
+
+ pushad
+
+ ;
+ ; Patch "jmp <EntryPoint>" over System Manager's VSM signature
+ ;
+ mov ax, (VSM_Header PTR [si]).EntryPoint
+ sub ax, 3
+ shl eax, 8
+ mov al, 0E9h ; JMP opcode
+ mov (VSM_Header PTR [si]).Signature, eax
+
+ ;
+ ; Patch SysMgr's Hardware structure
+ ;
+ lea bx, [si+SPECIAL_LOC]
+ mov bx, (InfoStuff PTR [bx]).HardwareInfo
+ ASSUME BX: PTR Hardware
+
+ mov ax, cs:[Device_ID]
+ mov [bx].Chipset_ID, ax
+
+ mov ax, cs:[PCI_MHz]
+ mov [bx].PCI_MHz, ax
+
+ movzx ax, cs:[Chipset_Rev]
+ mov [bx].Chipset_Rev, ax
+
+ mov eax, cs:[Chipset_Base]
+ mov [bx].Chipset_Base, eax
+
+ mov ax, cs:[Cpu_ID]
+ mov [bx].CPU_ID, ax
+
+ mov ax, cs:[Cpu_Revision]
+ mov [bx].CPU_Revision, ax
+
+ mov ax, cs:[CPU_MHz]
+ mov [bx].CPU_MHz, ax
+
+ mov ax, cs:[DRAM_MHz]
+ mov [bx].DRAM_MHz, ax
+
+ mov eax, cs:[TotalMemory]
+ mov [bx].SystemMemory, eax
+
+ mov eax, cs:[SysMgr_Location]
+ mov [bx].VSA_Location, eax
+ mov [si].SysStuff.SysMgr_Ptr, eax
+
+ mov ax, cs:[VSA_Size]
+ mov [bx].VSA_Size, ax
+ ASSUME BX:NOTHING
+
+ ;
+ ; Patch SysMgr's descriptors
+ ;
+ mov eax, (VSM_Header PTR [si]).DS_Limit
+ mov [SysMgrSize], ax
+ lea bx, (VSM_Header PTR [si])._DS
+ call Init_Descr
+
+ mov eax, SYSMGRS_STACK + VSM_STACK_FRAME
+ lea bx, (VSM_Header PTR [si])._SS
+ call Init_Descr
+
+ ;
+ ; Initialize the SysMgr's message queue
+ ;
+ call Init_Msg_Q
+
+ ;
+ ; Patch variables in SysMgr
+ ;
+ mov eax, cs:[Chipset_Base]
+ mov [si].SysStuff.Southbridge, eax
+
+ mov bx, si
+ add si, SPECIAL_LOC
+ ASSUME SI: PTR InfoStuff
+
+ movzx eax, [si].SysMgr_Stack
+ mov (VSM_Header PTR [bx]).SysStuff.SavedESP, eax
+
+ mov [si].SysMgr_VSM, edi
+
+ lea eax, (VSM_Header PTR [edi]).SysStuff.State + sizeof(SmiHeader)
+ add bx, [si].Header_Addr
+ mov [bx], eax
+
+ call Get_SMI_Base
+ mov [si].SMI_Base, eax
+
+ call Get_IRQ_Base
+ mov [si].IRQ_Base, eax
+
+
+Exit:
+
+ call SnagInterruptVectors ; Snapshot INT vectors from current VSA
+
+ popad
+ ret
+
+
+PatchSysMgr endp
+
+
+
+
+;*******************************************************************
+;
+; Loads a VSM into memory
+; Input:
+; DS:SI = ptr to VSM to load
+;
+;*******************************************************************
+Load_VSM proc
+
+ POST VSA_VSM_FOUND
+
+
+ ; Initialize the VSM's Header
+ ASSUME si:PTR VSM_Header
+
+ mov ax, [si].Flag
+ mov cs:[Requirments], ax
+ test ax, MASK SkipMe@@tag_i0
+ jz LoadIt
+
+Skip_VSM:
+ add esi, [si].VSM_Length ; Point to end of this VSM
+ call Flat_ESI
+ jmp Next_VSM
+LoadIt:
+
+ ; Initialize CPU dependent fields in the VSM's SMM header
+ call Set_CPU_Fields
+
+
+ ; Initialize EIP to VSM's entry point
+ movzx ecx, [si].EntryPoint
+ mov [si].SysStuff.State.Next_EIP, ecx
+
+ or [si].SysStuff.State.SMI_Flags, VSM_FLAGS
+
+
+ ; Store ptrs to certain System Manager structures for fast access
+ mov eax, cs:[SysMgrEntry]
+ add eax, SPECIAL_LOC
+ mov [si].SysStuff.SysMgr_Ptr, eax
+
+ mov eax, cs:[Chipset_Base]
+ mov al, SW_SMI
+ mov [si].SysStuff.Southbridge, eax
+
+
+
+ ; Initialize the VSM's resume header
+ ; Get size of DS segment
+ mov eax, [si].DS_Limit ; _DS.limit_15_0
+
+
+ inc eax ; Round to WORD boundary
+ and al, NOT 1
+ mov ecx, eax
+
+ ; Initialize the CS descriptor fields
+ ; NOTE: CS descriptor fields in SMM header are in "linear" format.
+ mov [si].SysStuff.State._CS.limit, ecx
+ mov [si].SysStuff.State._CS.attr, CODE_ATTR
+
+ mov [si].SysStuff.State.EFLAGS, VSM_EFLAGS
+ mov ecx, CR0 ; Preserve the CD & NW bit
+ and ecx, 60000000h
+ or ecx, VSM_CR0
+ mov [si].SysStuff.State.r_CR0, ecx
+ mov [si].SysStuff.State.r_DR7, VSM_DR7
+
+
+ ; Determine size of VSM's stack
+ movzx ecx, [si]._SS.limit_15_0 ; Get SS limit
+ or cx, cx ; Did VSM specify a stack size ?
+ jnz CheckMemSize
+ mov cx, VSM_STACK_SIZE ; No, use default stack size
+
+;*******************************************************************
+; SI = ptr to VSM image to be loaded
+; EAX = DS limit
+; ECX = stack size
+;*******************************************************************
+CheckMemSize:
+ add eax, ecx ; Compute descriptor limits
+ add ax, 15 ; Round up to next paragraph
+ and al, NOT 15
+ mov [si].DS_Limit,eax ; Update for use by BIOS scan
+
+ lea ebx, [edi+eax] ; If not enough memory, skip this VSM
+ cmp ebx, [VSA_End]
+ jae Skip_VSM
+ call AlignVSM
+ mov cs:[ModuleBase], edi ; Save the VSM module pointer in EDI
+
+
+;*******************************************************************
+;
+; Initialize VSM's descriptors
+;
+; SI = ptr to VSM image to be loaded
+; EAX = DS limit
+; EDI = Runtime address for this VSM
+;
+;*******************************************************************
+
+
+ ; Set VSM's CS selector to <load address> & 0xFFFFF
+ mov ecx, edi
+ and ecx, 000FFFFFh
+ shr ecx, 4
+ mov [si].SysStuff.State._CS.selector, cx
+
+ mov [si].SysStuff.State._CS.base, edi
+
+
+ ; Initialize the VSM's stack ptr
+ mov ebx, eax
+ and bl, 0FCh ; Round DOWN to nearest DWORD
+ sub bx, VSM_STACK_FRAME
+ mov [si].SysStuff.SavedESP, ebx
+
+ lea bx, [si]._DS ; Init DS
+ call Init_Descr
+
+ lea bx, [si]._ES ; Init ES
+ call Init_Descr
+
+ lea bx, [si]._SS ; Init SS
+ call Init_Descr
+
+
+ ; Initialize the VSM's message queue
+ call Init_Msg_Q
+
+
+ ; Update the doubly linked list of VSMs
+ mov ebx, edi
+ xchg ebx, cs:[Blink]
+ or ebx, ebx ; 1st VSM other than System Manager ?
+ jnz SetFlink
+
+ ; Store ptr to 1st VSM in the System Manager
+ mov eax, cs:[SysMgrEntry]
+ mov es:(VSM_Header PTR [eax]).SysStuff.Flink, edi
+
+ jmp Setlinks
+
+ ; EBX points to previous VSM
+SetFlink:
+ mov (VSM_Header PTR es:[ebx]).SysStuff.Flink, edi
+Setlinks:
+ mov [si].SysStuff.Blink, ebx
+
+ mov eax, cs:[Flink]
+ mov [si].SysStuff.Flink, eax
+
+ call CopyModule
+ ret
+
+
+Load_VSM endp
+
+
+END_MSG_QUEUE equ (MAX_MSG_CNT)*sizeof(Message)
+
+
+Init_Msg_Q proc
+
+ mov bx, offset VSM_Header.SysStuff.MsgQueue
+ mov [si].SysStuff.Qhead, bx ; Store queue head ptr
+ mov [si].SysStuff.Qtail, bx ; Store queue tail ptr
+ add bx, END_MSG_QUEUE ; End of queue
+ mov [si].SysStuff.EndMsgQ, bx
+ ret
+
+Init_Msg_Q endp
+
+
+
+
+
+
+
+;*******************************************************************
+;
+; Initializes a descriptor
+; On entry:
+; BX = ptr to descriptor
+; EAX = limit
+; EDI = base
+;
+;*******************************************************************
+Init_Descr proc
+ ASSUME bx: PTR Descriptor
+
+ push eax
+ push edi
+ mov [bx].limit_15_0, ax ; limit
+ shr eax, 16
+ mov [bx].limit_19_16, al
+ mov [bx].base_15_0, di ; base[15:00]
+ shr edi, 16
+ mov ax, di
+ mov [bx].base_23_16, al ; base[31:16]
+ mov [bx].base_31_24, ah
+ mov [bx].attr, DATA_ATTR ; attribute
+ pop edi
+ pop eax
+ ret
+
+ ASSUME bx: NOTHING
+
+Init_Descr endp
+
+
+;*******************************************************************
+;
+; Copies a module to its runtime location.
+; On Entry:
+; DS:SI - ptr to source
+; ES:EDI - ptr to destination
+; On Exit:
+; CF - set if error. AX = error code
+;*******************************************************************
+CopyModule proc
+
+
+
+ ; Get length of segment & compute size of BSS
+ mov ecx, [si].VSM_Length
+ movzx edx, [si]._DS.limit_15_0
+ sub edx, ecx
+
+
+ call Flat_ESI
+
+
+ ;
+ ; Copy the VSM image to its runtime location
+ ;
+
+if VERIFY_VSM_COPY
+ push ecx ; Save byte count & ptrs
+ push esi
+ push edi
+endif
+
+ POST VSA_COPY_START ; 14h
+
+ mov ah, cl
+ shr ecx, 2 ; Convert BYTE count to DWORD count
+ cld
+ rep movsd [edi], es:[esi]
+
+ and ah, 3 ; Copy remaining bytes
+ mov cl, ah
+ rep movsb [edi], es:[esi]
+
+ POST VSA_COPY_END ; 15h
+
+if VERIFY_VSM_COPY
+
+ pop edi ; Restore original ptrs and byte count
+ pop esi
+ pop ecx
+
+ ;
+ ; Verify the VSM image copy
+ ;
+ mov ebx, edi ; Save ptr to start of VSM
+ shr ecx, 2 ; Convert byte count to dword count
+
+ POST VSA_VRFY_START ; 1Ch
+
+ repe cmpsd es:[esi], [edi]
+ jne VerifyError
+
+ mov cl, ah ; Compare leftover byte(s)
+ repe cmpsb es:[esi], [edi]
+ je Verify_Passed
+
+VerifyError:
+
+ mov ax, ERR_VERIFY
+ stc
+ jmp Exit
+
+Verify_Passed:
+ POST VSA_VRFY_END ; 1Dh
+
+endif ; VERIFY_VSM_COPY
+
+
+
+
+ POST VSA_FILL_START
+
+ ;
+ ; Clear the uninitialized data space
+ ;
+ mov ecx, edx ; Fill BSS with zeros
+ shr ecx, 2
+ xor eax, eax
+ rep stosd [edi]
+ mov cl, dl
+ and cl, 3
+ je BSS_Cleared
+ rep stosb [edi]
+BSS_Cleared:
+
+
+ POST VSA_FILL_END
+
+
+
+
+ ; Search the image for the next VSM.
+ ; Some VSMs lie about their size. Search a byte at a time
+ ; for 'VSM ', first backward, then forward.
+Next_VSM::
+ mov edx, -1 ; Start search backwards
+MAX_SEARCH equ 16
+Search:
+ mov cx, MAX_SEARCH ; Range in bytes to scan for VSM
+
+SearchNext:
+ cmp dword ptr es:[esi], VSM_SIGNATURE
+ je NextVSMfound
+ add esi, edx
+ loop SearchNext
+
+ add esi, MAX_SEARCH
+ neg edx ; Look the other direction
+ cmp dl, 1 ; Have we already looked in that direction ?
+ je Search
+ jmp OK_Exit ; No more VSMs found
+
+
+NextVSMfound:
+
+ ; Convert ESI into DS:SI format
+ mov edx, esi
+ shr edx, 4
+ mov ds, dx
+ and esi, 0000000Fh
+OK_Exit:
+ clc
+Exit: ret
+
+
+
+CopyModule endp
+
+
+;*******************************************************************
+; Converts DS:SI to a flat ptr in ESI.
+;*******************************************************************
+Flat_ESI proc
+
+ push eax
+ mov ax, ds ; Convert DS:SI to a flat ptr
+ movzx eax, ax
+ shl eax, 4
+ movzx esi, si
+ add esi, eax
+ pop eax
+ ret
+
+Flat_ESI endp
+
+
+BIOS_ECX dd 0
+BIOS_EDX dd 0
+TotalMemory dd 0
+SysMgr_Location dd 0
+VSA_End dd 0
+Chipset_Base dd 0
+SysMgrEntry dd 00000000h
+ModuleBase dd 00000000h
+Blink dd 00000000h
+Flink dd 00000000h
+InitParam1 dd 0
+InitParam2 dd 0
+
+SysMgrSize dw 0
+VSA_Size dw 0
+Errors dw 0
+Device_ID dw 0
+Cpu_ID dw 0
+Cpu_Revision dw 0
+SysCall_Code dw SYS_BIOS_INIT
+Requirments dw 0
+CPU_MHz dw 0
+PCI_MHz dw 0
+DRAM_MHz dw 0
+Chipset_Rev db 0
+SetupComplete db 0
+LoadFlag db 0
+
+Flat_Descriptor Descriptor {0FFFFh, 0000h, 00h, DATA_ATTR, 8Fh, 00h, 0}
+
+Msg_CompareError db "...compare error at 0x$"
+Msg_Not_DOS_BUILD db CR,LF, "This version of INIT doesn't support DOS install.$"
+
+
+ END VSA_Installation
+
+
+