misc.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 724 行 · 第 1/2 页
C
724 行
/*++
Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
Misc.c
Abstract:
Helper Routines that use a PXE-enabled NIC option ROM.
Revision History
--*/
#include "BiosSnp16.h"
#define TO_SEGMENT(x) ((UINT16) (DriverLibRShiftU64 ((UINT32) (x), 4) & 0xF000))
#define TO_OFFSET(x) ((UINT16) ((UINT32)(x) & 0xFFFF))
#define PARAGRAPH_SIZE 0x10
#define IVT_BASE 0x00000000
#pragma pack(1)
typedef struct {
UINT16 Signature; // 0xaa55
UINT8 ROMlength; // size of this ROM in 512 byte blocks
UINT8 InitEntryPoint[4]; // a jump to the initialization routine
UINT8 Reserved[0xf]; // various
UINT16 PxeRomIdOffset; // offset of UNDI, $BC$, or BUSD ROM ID structure
UINT16 PcirHeaderOffset; // offset of PCI Expansion Header
UINT16 PnpHeaderOffset; // offset of Plug and Play Expansion Header
} OPTION_ROM_HEADER;
#pragma pack()
static UINT32 CachedVectorAddress[0x100];
EFI_STATUS
CacheVectorAddress (
UINT8 VectorNumber
)
{
UINT32 *pAddress;
pAddress = (UINT32 *) (IVT_BASE + VectorNumber * 4);
CachedVectorAddress[VectorNumber] = *pAddress;
return EFI_SUCCESS;
}
EFI_STATUS
RestoreCachedVectorAddress (
UINT8 VectorNumber
)
{
UINT32 *pAddress;
pAddress = (UINT32 *) (IVT_BASE + VectorNumber * 4);
*pAddress = CachedVectorAddress[VectorNumber];
return EFI_SUCCESS;
}
STATIC
VOID
Print_Undi_Loader_Table (
VOID *UndiLoaderStructure
)
{
UNDI_Loader_t *DisplayPointer;
DisplayPointer = (UNDI_Loader_t *) UndiLoaderStructure;
DEBUG ((EFI_D_NET,"Before Parsing the table contents, the table itself lives\n"));
DEBUG ((EFI_D_NET,"\tat the address 0x%X\n\r", (UINT32) UndiLoaderStructure));
DEBUG ((EFI_D_NET,"\n\rStatus = 0x%X\n\r", DisplayPointer->Status));
DEBUG ((EFI_D_NET,"\t_AX_= 0x%X\n\r",DisplayPointer->_AX_));
DEBUG ((EFI_D_NET,"\t_BX_= 0x%X\n\r",DisplayPointer->_BX_));
DEBUG ((EFI_D_NET,"\t_DX_= 0x%X\n\r",DisplayPointer->_DX_));
DEBUG ((EFI_D_NET,"\t_DI_= 0x%X\n\r",DisplayPointer->_DI_));
DEBUG ((EFI_D_NET,"\t_ES_= 0x%X\n\r",DisplayPointer->_ES_));
DEBUG ((EFI_D_NET,"\tUNDI_DS= 0x%X\n\r",DisplayPointer->UNDI_DS));
DEBUG ((EFI_D_NET,"\tUNDI_CS= 0x%X\n\r",DisplayPointer->UNDI_CS));
DEBUG ((EFI_D_NET,"\tPXEptr:SEG= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.segment));
DEBUG ((EFI_D_NET,"\tPXEptr:OFF= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.offset));
DEBUG ((EFI_D_NET,"\tPXENVptr:SEG= 0x%X\n\r",(UINT16) DisplayPointer->PXENVptr.segment));
DEBUG ((EFI_D_NET,"\tPXENVptr:OFF= 0x%X\n\r",(UINT16) DisplayPointer->PXENVptr.offset));
}
STATIC
VOID
Print_ROMID_Table (
IN VOID *RomIDStructure
)
/*++
Simple table dumper. The ROMID table is necessary in order to effect
the "Early UNDI" trick. Herein, the UNDI layer can be loaded in the
pre-boot phase without having to download a Network Boot Program
across the wire. It is required in the implementation in that we
are not using PXE.
--*/
{
UNDI_ROMID_t *DisplayPointer;
DisplayPointer = (UNDI_ROMID_t *) RomIDStructure;
DEBUG ((EFI_D_NET,"Before Parsing the table contents, the table itself lives\n"));
DEBUG ((EFI_D_NET,"\tat the address 0x%X\n\r", (UINT32) RomIDStructure));
DEBUG ((EFI_D_NET,"\n\rROMID %c%c%c%c\n\r",
DisplayPointer->Signature[0],
DisplayPointer->Signature[1],
DisplayPointer->Signature[2],
DisplayPointer->Signature[3]
));
DEBUG ((EFI_D_NET,"Length of this structure in bytes = 0x%X\n\r",
DisplayPointer->StructLength));
DEBUG ((EFI_D_NET,"Use to make byte checksum of this structure == zero is = 0x%X\n\r",
DisplayPointer->StructCksum));
DEBUG ((EFI_D_NET,"Structure format revision number= 0x%X\n\r",
DisplayPointer->StructRev));
DEBUG ((EFI_D_NET,"API Revision number = 0x%X 0x%X 0x%X\n\r",
DisplayPointer->UNDI_Rev[0],
DisplayPointer->UNDI_Rev[1],
DisplayPointer->UNDI_Rev[2]));
DEBUG ((EFI_D_NET,"Offset of UNDI loader routine in the option ROM image= 0x%X\n\r",
DisplayPointer->UNDI_Loader));
DEBUG ((EFI_D_NET,"From the data above, the absolute entry point of the UNDI loader is\n\r"));
DEBUG ((EFI_D_NET,"\tat address 0x%X\n\r",
(UINT32)(DisplayPointer->UNDI_Loader +
((UINT32)(DisplayPointer-0x20) & 0xFFFF0))));
DEBUG ((EFI_D_NET,"Minimum stack segment size, in bytes,\n\r"));
DEBUG ((EFI_D_NET,"needed to load and run the UNDI= 0x%X \n\r",
DisplayPointer->StackSize));
DEBUG ((EFI_D_NET,"UNDI runtime code and data = 0x%X\n\r",
DisplayPointer->DataSize));
DEBUG ((EFI_D_NET,"Segment size = 0x%X\n\r",
DisplayPointer->CodeSize));
DEBUG ((EFI_D_NET,"\n\rBus Type = %c%c%c%c\n\r",
DisplayPointer->BusType[0],
DisplayPointer->BusType[1],
DisplayPointer->BusType[2],
DisplayPointer->BusType[3]
));
}
STATIC
VOID
Print_PXE_Table (
IN VOID* PxeTable
)
{
PXE_t *DisplayPointer;
UINTN idx;
UINT8 *dptr;
DisplayPointer = (PXE_t *) PxeTable;
dptr = (UINT8*) PxeTable;
DEBUG((EFI_D_NET,"This is the PXE table at address 0x%X\n\r", PxeTable));
DEBUG((EFI_D_NET,"A dump of the 0x%X bytes is:\n\r", sizeof (PXE_t)));
for (idx= 0; idx < sizeof(PXE_t); idx++) {
if (!(idx % 0x10)) {
DEBUG((EFI_D_NET,"\t\n\r"));
}
DEBUG ((EFI_D_NET," 0x%X ", *dptr++));
}
DEBUG((EFI_D_NET,"\n\r"));
DEBUG ((EFI_D_NET,"\n\rPXE %c%c%c%c%c%c\n\r",
DisplayPointer->Signature[0],
DisplayPointer->Signature[1],
DisplayPointer->Signature[2],
DisplayPointer->Signature[3]));
DEBUG ((EFI_D_NET,"Length of this structure in bytes = 0x%X\n\r",
DisplayPointer->StructLength));
DEBUG ((EFI_D_NET,"Use to make byte checksum of this structure == zero is = 0x%X\n\r",
DisplayPointer->StructCksum));
DEBUG ((EFI_D_NET,"Structure format revision number = 0x%X\n\r",
DisplayPointer->StructRev));
DEBUG ((EFI_D_NET,"Must be zero, is equal to 0x%X\n\r",
DisplayPointer->reserved1));
DEBUG ((EFI_D_NET,"Far pointer to UNDI ROMID = 0x%X\n\r",
(UINT32) (DisplayPointer->UNDI.segment << 0x4 | DisplayPointer->UNDI.offset)));
DEBUG ((EFI_D_NET,"Far pointer to base-code ROMID = 0x%X\n\r",
(UINT32) ((DisplayPointer->Base.segment << 0x04) | DisplayPointer->Base.offset)));
DEBUG ((EFI_D_NET,"16bit stack segment API entry point. This will be seg:off in \n\r"));
DEBUG ((EFI_D_NET,"real mode and sel:off in 16:16 protected mode = 0x%X:0x%X\n\r",
DisplayPointer->EntryPointSP.segment,
DisplayPointer->EntryPointSP.offset));
DEBUG ((EFI_D_NET,"\n\tNOTE to the implementer\n\tThis is the entry to use for call-ins\n\r"));
DEBUG ((EFI_D_NET,"32bit stack segment API entry point. This will be sel:off. \n\r"));
DEBUG ((EFI_D_NET,"In real mode, sel == 0 = 0x%X:0x%X\n\r",
DisplayPointer->EntryPointESP.segment, DisplayPointer->EntryPointESP.offset));
DEBUG ((EFI_D_NET,"Reserved2 value, must be zero, is equal to 0x%X\n\r",
DisplayPointer->reserved2));
DEBUG ((EFI_D_NET,"Number of segment descriptors in this structur = 0x%X\n\r",
(UINT8) DisplayPointer->SegDescCnt));
DEBUG ((EFI_D_NET,"First segment descriptor in GDT assigned to PXE = 0x%X\n\r",
(UINT16) DisplayPointer->FirstSelector));
DEBUG ((EFI_D_NET,"The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
(UINT16) DisplayPointer->Stack.Seg_Addr,
(UINT32) DisplayPointer->Stack.Phy_Addr,
(UINT16) DisplayPointer->Stack.Seg_Size));
DEBUG ((EFI_D_NET,"The UNDIData is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
(UINT16) DisplayPointer->UNDIData.Seg_Addr,
(UINT32) DisplayPointer->UNDIData.Phy_Addr,
(UINT16) DisplayPointer->UNDIData.Seg_Size));
DEBUG ((EFI_D_NET,"The UNDICodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
(UINT16) DisplayPointer->UNDICode.Seg_Addr,
(UINT32) DisplayPointer->UNDICode.Phy_Addr,
(UINT16) DisplayPointer->UNDICode.Seg_Size));
DEBUG ((EFI_D_NET,"The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
(UINT16) DisplayPointer->UNDICodeWrite.Seg_Addr,
(UINT32) DisplayPointer->UNDICodeWrite.Phy_Addr,
(UINT16) DisplayPointer->UNDICodeWrite.Seg_Size));
DEBUG ((EFI_D_NET,"The BC_Data is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
(UINT16) DisplayPointer->BC_Data.Seg_Addr,
(UINT32) DisplayPointer->BC_Data.Phy_Addr,
(UINT16) DisplayPointer->BC_Data.Seg_Size));
DEBUG ((EFI_D_NET,"The BC_Code is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
(UINT16) DisplayPointer->BC_Code.Seg_Addr,
(UINT32) DisplayPointer->BC_Code.Phy_Addr,
(UINT16) DisplayPointer->BC_Code.Seg_Size));
DEBUG ((EFI_D_NET,"The BC_CodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
(UINT16) DisplayPointer->BC_CodeWrite.Seg_Addr,
(UINT32) DisplayPointer->BC_CodeWrite.Phy_Addr,
(UINT16) DisplayPointer->BC_CodeWrite.Seg_Size));
}
VOID
Print_PXENV_Table(
IN VOID* PxenvTable
)
{
PXENV_t *DisplayPointer;
DisplayPointer = (PXENV_t *) PxenvTable;
DEBUG ((EFI_D_NET,"\n\rPXENV+ %c%c%c%c%c%c\n\r",
DisplayPointer->Signature[0],
DisplayPointer->Signature[1],
DisplayPointer->Signature[2],
DisplayPointer->Signature[3],
DisplayPointer->Signature[4],
DisplayPointer->Signature[5]));
DEBUG ((EFI_D_NET,"PXE version number. \n\r\tLSB is minor version. \n\r\tMSB is major version = 0x%X\n\r",
DisplayPointer->Version));
DEBUG ((EFI_D_NET,"Length of PXE-2.0 Entry Point structure in bytes = 0x%X\n\r",
DisplayPointer->StructLength));
DEBUG ((EFI_D_NET,"Used to make structure checksum equal zero is now = 0x%X\n\r", DisplayPointer->StructCksum));
DEBUG ((EFI_D_NET,"Real mode API entry point segment:offset. = 0x%X\n\r", DisplayPointer->RMEntry));
DEBUG ((EFI_D_NET,"Protected mode API entry point = 0x%X\n\r", DisplayPointer->PMEntryOff));
DEBUG ((EFI_D_NET," segment:offset. This will always be zero. \n\r"));
DEBUG ((EFI_D_NET,"Protected mode API calls = 0x%X\n\r",DisplayPointer->PMEntrySeg));
DEBUG ((EFI_D_NET,"Real mode stack segment = 0x%X\n\r", DisplayPointer->StackSeg));
DEBUG ((EFI_D_NET,"Stack segment size in bytes = 0x%X\n\r", DisplayPointer->StackSize));
DEBUG ((EFI_D_NET,"Real mode base-code code segment = 0x%X\n\r", DisplayPointer->BaseCodeSeg));
DEBUG ((EFI_D_NET,"Base-code code segment size = 0x%X\n\r", DisplayPointer->BaseCodeSize));
DEBUG ((EFI_D_NET,"Real mode base-code data segment = 0x%X\n\r", DisplayPointer->BaseDataSeg));
DEBUG ((EFI_D_NET,"Base-code data segment size = 0x%X\n\r", DisplayPointer->BaseDataSize));
DEBUG ((EFI_D_NET,"UNDI code segment size in bytes = 0x%X\n\r",
DisplayPointer->UNDICodeSize));
DEBUG ((EFI_D_NET,"Real mode segment:offset pointer \n\r\tto PXE Runtime ID structure, address = 0x%X\n\r",
DisplayPointer->RuntimePtr));
DEBUG ((EFI_D_NET,"From above, we have a linear address of 0x%X\n\r",
(UINT32) ( ((UINT32)(DisplayPointer->RuntimePtr) & 0xFFFF) +
(((UINT32)(DisplayPointer->RuntimePtr) & 0xFFFF0000) >> 12))));
}
static
UINT8
CheckSum (
UINT8 *Start,
UINTN Length
)
{
UINT8 Sum;
Sum = 0;
do {
Sum += *Start++;
} while (--Length);
return Sum;
}
#define pOptionRomHeader ((OPTION_ROM_HEADER *)RomAddress)
EFI_STATUS
LaunchBaseCode(
EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
UINTN RomAddress
)
/*++
If available, launch the BaseCode from a NIC option ROM.
This should install the !PXE and PXENV+ structures in memory for
subsequent use.
--*/
{
EFI_STATUS Status;
IA32_RegisterSet_t InOutRegs;
UNDI_ROMID_t *RomIdTableAddress;
UNDI_Loader_t *UndiLoaderTable;
UINT16 Segment;
UINT16 *StackPointer;
VOID* Buffer;
UINTN Size;
PXE_t *pPxe;
UINT32 RomLength;
UINTN PciSegment;
UINTN Bus;
UINTN Device;
UINTN Function;
DEBUG ((EFI_D_NET,"\n\r\n\rCheck for the UNDI ROMID Signature\n\r"));
// paranoia - check structures for validity
if (CheckSum((UINT8 *)RomAddress, RomLength = pOptionRomHeader->ROMlength << 9)) {
DEBUG ((EFI_D_ERROR,"ROM Header Checksum Error\n\r"));
return EFI_NOT_FOUND;
}
RomIdTableAddress = (UNDI_ROMID_t *)(RomAddress+pOptionRomHeader->PxeRomIdOffset);
if ((UINTN)(pOptionRomHeader->PxeRomIdOffset + RomIdTableAddress->StructLength) > RomLength) {
DEBUG ((EFI_D_ERROR,"ROM ID Offset Error\n\r"));
return EFI_NOT_FOUND;
}
// see if this is a header for an UNDI ROM ID structure (vs. a $BC$ or BUSD type)
if (EfiCompareMem(RomIdTableAddress->Signature, UNDI_ROMID_SIG, sizeof RomIdTableAddress->Signature)) {
DEBUG ((EFI_D_ERROR,"No ROM ID Structure found....\n\r"));
return EFI_NOT_FOUND; // its not - keep looking
}
if (CheckSum((UINT8 *)RomIdTableAddress, RomIdTableAddress->StructLength)) {
DEBUG ((EFI_D_ERROR,"ROM ID Checksum Error\n\r"));
return EFI_NOT_FOUND;
}
Print_ROMID_Table(RomIdTableAddress);
DEBUG ((EFI_D_NET,"The ROM ID is located at 0x%X\n\r",
RomIdTableAddress));
DEBUG ((EFI_D_NET,"With an UNDI Loader located at 0x%X\n\r",
RomAddress + RomIdTableAddress->UNDI_Loader));
// found an UNDI ROM ID structure
SimpleNetworkDevice->NII.ImageAddr = RomAddress;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?