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 + -
显示快捷键?