/** Initializes a basic mutual exclusion lock. This function initializes a basic mutual exclusion lock to the released state and returns the lock. Each lock provides mutual exclusion access at its task priority level. Since there is no preemption or multiprocessor support in EFI, acquiring the lock only consists of raising to the locks TPL. If Lock is NULL, then ASSERT(). If Priority is not a valid TPL value, then ASSERT(). @param Lock A pointer to the lock data structure to initialize. @param Priority EFI TPL is associated with the lock. @return The lock. **/ EFI_LOCK * InitializeLock ( IN OUT EFI_LOCK *Lock, IN EFI_TPL Priority ) { return EfiInitializeLock (Lock, Priority); }
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; EfiInitializeRuntimeDriverLib (ImageHandle, SystemTable, NULL); EfiInitializeLock (&mModuleGlobal.RtcLock, EFI_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; }
/** Create a socket with initial data SockInitData. @param SockInitData Pointer to the initial data of the socket. @return Pointer to the newly created socket, return NULL when exception occured. **/ SOCKET * SockCreate ( IN SOCK_INIT_DATA *SockInitData ) { SOCKET *Sock; SOCKET *Parent; EFI_STATUS Status; ASSERT ((SockInitData != NULL) && (SockInitData->ProtoHandler != NULL)); ASSERT (SockInitData->Type == SockStream); ASSERT ((SockInitData->ProtoData != NULL) && (SockInitData->DataSize <= PROTO_RESERVED_LEN)); Parent = SockInitData->Parent; if ((Parent != NULL) && (Parent->ConnCnt == Parent->BackLog)) { DEBUG ( (EFI_D_ERROR, "SockCreate: Socket parent has " "reached its connection limit with %d ConnCnt and %d BackLog\n", Parent->ConnCnt, Parent->BackLog) ); return NULL; } Sock = AllocateZeroPool (sizeof (SOCKET)); if (NULL == Sock) { DEBUG ((EFI_D_ERROR, "SockCreate: No resource to create a new socket\n")); return NULL; } InitializeListHead (&Sock->Link); InitializeListHead (&Sock->ConnectionList); InitializeListHead (&Sock->ListenTokenList); InitializeListHead (&Sock->RcvTokenList); InitializeListHead (&Sock->SndTokenList); InitializeListHead (&Sock->ProcessingSndTokenList); EfiInitializeLock (&(Sock->Lock), TPL_CALLBACK); Sock->SndBuffer.DataQueue = NetbufQueAlloc (); if (NULL == Sock->SndBuffer.DataQueue) { DEBUG ((EFI_D_ERROR, "SockCreate: No resource to allocate" " SndBuffer for new socket\n")); goto OnError; } Sock->RcvBuffer.DataQueue = NetbufQueAlloc (); if (NULL == Sock->RcvBuffer.DataQueue) { DEBUG ((EFI_D_ERROR, "SockCreate: No resource to allocate " "RcvBuffer for new socket\n")); goto OnError; } Sock->Signature = SOCK_SIGNATURE; Sock->Parent = Parent; Sock->BackLog = SockInitData->BackLog; Sock->ProtoHandler = SockInitData->ProtoHandler; Sock->SndBuffer.HighWater = SockInitData->SndBufferSize; Sock->RcvBuffer.HighWater = SockInitData->RcvBufferSize; Sock->Type = SockInitData->Type; Sock->DriverBinding = SockInitData->DriverBinding; Sock->State = SockInitData->State; Sock->CreateCallback = SockInitData->CreateCallback; Sock->DestroyCallback = SockInitData->DestroyCallback; Sock->Context = SockInitData->Context; Sock->SockError = EFI_ABORTED; Sock->SndBuffer.LowWater = SOCK_BUFF_LOW_WATER; Sock->RcvBuffer.LowWater = SOCK_BUFF_LOW_WATER; // // Install protocol on Sock->SockHandle // CopyMem ( &(Sock->NetProtocol.TcpProtocol), SockInitData->Protocol, sizeof (EFI_TCP4_PROTOCOL) ); // // copy the protodata into socket // CopyMem (Sock->ProtoReserved, SockInitData->ProtoData, SockInitData->DataSize); Status = gBS->InstallMultipleProtocolInterfaces ( &Sock->SockHandle, &gEfiTcp4ProtocolGuid, &(Sock->NetProtocol.TcpProtocol), NULL ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "SockCreate: Install TCP protocol in " "socket failed with %r\n", Status)); goto OnError; } if (Parent != NULL) { ASSERT (Parent->BackLog > 0); ASSERT (SOCK_IS_LISTENING (Parent)); // // need to add it into Parent->ConnectionList // if the Parent->ConnCnt < Parent->BackLog // Parent->ConnCnt++; DEBUG ( (EFI_D_NET, "SockCreate: Create a new socket and add to parent, now conncnt is %d\n", Parent->ConnCnt) ); InsertTailList (&Parent->ConnectionList, &Sock->ConnectionList); } if (Sock->CreateCallback != NULL) { Status = Sock->CreateCallback (Sock, Sock->Context); if (EFI_ERROR (Status)) { goto OnError; } } return Sock; OnError: if (Sock->SockHandle != NULL) { gBS->UninstallMultipleProtocolInterfaces ( Sock->SockHandle, &gEfiTcp4ProtocolGuid, &(Sock->NetProtocol.TcpProtocol), NULL ); } if (NULL != Sock->SndBuffer.DataQueue) { NetbufQueFree (Sock->SndBuffer.DataQueue); } if (NULL != Sock->RcvBuffer.DataQueue) { NetbufQueFree (Sock->RcvBuffer.DataQueue); } FreePool (Sock); return NULL; }
/** Start this driver on ControllerHandle. This service is called by the EFI boot service ConnectController(). In order to make drivers as small as possible, there are a few calling restrictions for this service. ConnectController() must follow these calling restrictions. If any other agent wishes to call Start() it must also follow these calling restrictions. @param This Protocol instance pointer. @param ControllerHandle Handle of device to bind driver to. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver is added to ControllerHandle @retval EFI_DEVICE_ERROR This driver could not be started due to a device error @retval other This driver does not support this device **/ EFI_STATUS EFIAPI SimpleNetworkDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii; EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath; EFI_STATUS Status; PXE_UNDI *Pxe; SNP_DRIVER *Snp; VOID *Address; EFI_HANDLE Handle; PXE_PCI_CONFIG_INFO ConfigInfo; PCI_TYPE00 *ConfigHeader; UINT32 *TempBar; UINT8 BarIndex; PXE_STATFLAGS InitStatFlags; DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() ")); Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &NiiDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->LocateDevicePath ( &gEfiPciIoProtocolGuid, &NiiDevicePath, &Handle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( Handle, &gEfiPciIoProtocolGuid, (VOID **) &mPciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } // // Get the NII interface. // Status = gBS->OpenProtocol ( Controller, &gEfiNetworkInterfaceIdentifierProtocolGuid_31, (VOID **) &Nii, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); return Status; } DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n")); Pxe = (PXE_UNDI *) (UINTN) (Nii->Id); if (Calc8BitCksum (Pxe, Pxe->hw.Len) != 0) { DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n")); goto NiiError; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) { // // We can get any packets. // } else if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) { // // We need to be able to get broadcast packets for DHCP. // If we do not have promiscuous support, we must at least have // broadcast support or we cannot do DHCP! // } else { DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support.")); goto NiiError; } // // OK, we like this UNDI, and we know snp is not already there on this handle // Allocate and initialize a new simple network protocol structure. // Status = mPciIo->AllocateBuffer ( mPciIo, AllocateAnyPages, EfiBootServicesData, SNP_MEM_PAGES (sizeof (SNP_DRIVER)), &Address, 0 ); if (Status != EFI_SUCCESS) { DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n")); goto NiiError; } Snp = (SNP_DRIVER *) (UINTN) Address; ZeroMem (Snp, sizeof (SNP_DRIVER)); Snp->PciIo = mPciIo; Snp->Signature = SNP_DRIVER_SIGNATURE; EfiInitializeLock (&Snp->Lock, TPL_NOTIFY); Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; Snp->Snp.Start = SnpUndi32Start; Snp->Snp.Stop = SnpUndi32Stop; Snp->Snp.Initialize = SnpUndi32Initialize; Snp->Snp.Reset = SnpUndi32Reset; Snp->Snp.Shutdown = SnpUndi32Shutdown; Snp->Snp.ReceiveFilters = SnpUndi32ReceiveFilters; Snp->Snp.StationAddress = SnpUndi32StationAddress; Snp->Snp.Statistics = SnpUndi32Statistics; Snp->Snp.MCastIpToMac = SnpUndi32McastIpToMac; Snp->Snp.NvData = SnpUndi32NvData; Snp->Snp.GetStatus = SnpUndi32GetStatus; Snp->Snp.Transmit = SnpUndi32Transmit; Snp->Snp.Receive = SnpUndi32Receive; Snp->Snp.WaitForPacket = NULL; Snp->Snp.Mode = &Snp->Mode; Snp->TxRxBufferSize = 0; Snp->TxRxBuffer = NULL; if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) { Snp->IfNum = Nii->IfNum; } else { Snp->IfNum = (UINT8) (Nii->IfNum & 0xFF); } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) { Snp->IsSwUndi = FALSE; Snp->IssueUndi32Command = &IssueHwUndiCommand; } else { Snp->IsSwUndi = TRUE; if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) { Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) Pxe->sw.EntryPoint; } else { Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) ((UINT8) (UINTN) Pxe + Pxe->sw.EntryPoint); } } // // Allocate a global CPB and DB buffer for this UNDI interface. // we do this because: // // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be // within 2GB limit, create them here and map them so that when undi calls // v2p callback to check if the physical address is < 2gb, we will pass. // // -This is not a requirement for 3.1 or later UNDIs but the code looks // simpler if we use the same cpb, db variables for both old and new undi // interfaces from all the SNP interface calls (we don't map the buffers // for the newer undi interfaces though) // . // -it is OK to allocate one global set of CPB, DB pair for each UNDI // interface as EFI does not multi-task and so SNP will not be re-entered! // Status = mPciIo->AllocateBuffer ( mPciIo, AllocateAnyPages, EfiBootServicesData, SNP_MEM_PAGES (4096), &Address, 0 ); if (Status != EFI_SUCCESS) { DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n")); goto Error_DeleteSNP; } Snp->Cpb = (VOID *) (UINTN) Address; Snp->Db = (VOID *) ((UINTN) Address + 2048); // // PxeStart call is going to give the callback functions to UNDI, these callback // functions use the BarIndex values from the snp structure, so these must be initialized // with default values before doing a PxeStart. The correct values can be obtained after // getting the config information from UNDI // Snp->MemoryBarIndex = 0; Snp->IoBarIndex = 1; // // we need the undi init information many times in this snp code, just get it // once here and store it in the snp driver structure. to get Init Info // from UNDI we have to start undi first. // Status = PxeStart (Snp); if (Status != EFI_SUCCESS) { goto Error_DeleteSNP; } Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO; Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED; Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED; Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED; Snp->Cdb.DBsize = (UINT16) sizeof (Snp->InitInfo); Snp->Cdb.DBaddr = (UINT64)(UINTN) (&Snp->InitInfo); Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE; Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; Snp->Cdb.IFnum = Snp->IfNum; Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; DEBUG ((EFI_D_NET, "\nSnp->undi.get_init_info() ")); (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb); // // Save the INIT Stat Code... // InitStatFlags = Snp->Cdb.StatFlags; if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) { DEBUG ((EFI_D_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode)); PxeStop (Snp); goto Error_DeleteSNP; } Snp->Cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO; Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED; Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED; Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED; Snp->Cdb.DBsize = (UINT16) sizeof (ConfigInfo); Snp->Cdb.DBaddr = (UINT64)(UINTN) &ConfigInfo; Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE; Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; Snp->Cdb.IFnum = Snp->IfNum; Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; DEBUG ((EFI_D_NET, "\nSnp->undi.get_config_info() ")); (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb); if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) { DEBUG ((EFI_D_NET, "\nSnp->undi.config_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode)); PxeStop (Snp); goto Error_DeleteSNP; } // // Find the correct BAR to do IO. // // // Enumerate through the PCI BARs for the device to determine which one is // the IO BAR. Save the index of the BAR into the adapter info structure. // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped // ConfigHeader = (PCI_TYPE00 *) ConfigInfo.Config.Byte; TempBar = (UINT32 *) ConfigHeader->Device.Bar; for (BarIndex = 0; BarIndex <= 5; BarIndex++) { if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) { // // This is a 64-bit memory bar, skip this and the // next bar as well. // TempBar++; } if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) { Snp->IoBarIndex = BarIndex; break; } TempBar++; } // // Initialize simple network protocol mode structure // Snp->Mode.State = EfiSimpleNetworkStopped; Snp->Mode.HwAddressSize = Snp->InitInfo.HWaddrLen; Snp->Mode.MediaHeaderSize = Snp->InitInfo.MediaHeaderLen; Snp->Mode.MaxPacketSize = Snp->InitInfo.FrameDataLen; Snp->Mode.NvRamAccessSize = Snp->InitInfo.NvWidth; Snp->Mode.NvRamSize = Snp->InitInfo.NvCount * Snp->Mode.NvRamAccessSize; Snp->Mode.IfType = Snp->InitInfo.IFtype; Snp->Mode.MaxMCastFilterCount = Snp->InitInfo.MCastFilterCnt; Snp->Mode.MCastFilterCount = 0; switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) { case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED: Snp->Mode.MediaPresentSupported = TRUE; break; case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED: default: Snp->Mode.MediaPresentSupported = FALSE; } switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) { case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED: Snp->MediaStatusSupported = TRUE; break; case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED: default: Snp->MediaStatusSupported = FALSE; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) { Snp->Mode.MacAddressChangeable = TRUE; } else { Snp->Mode.MacAddressChangeable = FALSE; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) { Snp->Mode.MultipleTxSupported = TRUE; } else { Snp->Mode.MultipleTxSupported = FALSE; } Snp->Mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) { Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) { Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) { Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) { Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) { Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; } Snp->Mode.ReceiveFilterSetting = 0; // // need to get the station address to save in the mode structure. we need to // initialize the UNDI first for this. // Snp->TxRxBufferSize = Snp->InitInfo.MemoryRequired; Status = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE); if (EFI_ERROR (Status)) { PxeStop (Snp); goto Error_DeleteSNP; } Status = PxeGetStnAddr (Snp); if (Status != EFI_SUCCESS) { DEBUG ((EFI_D_ERROR, "\nSnp->undi.get_station_addr() failed.\n")); PxeShutdown (Snp); PxeStop (Snp); goto Error_DeleteSNP; } Snp->Mode.MediaPresent = FALSE; // // We should not leave UNDI started and initialized here. this DriverStart() // routine must only find and attach the SNP interface to UNDI layer that it // finds on the given handle! // The UNDI layer will be started when upper layers call Snp->start. // How ever, this DriverStart() must fill up the snp mode structure which // contains the MAC address of the NIC. For this reason we started and // initialized UNDI here, now we are done, do a shutdown and stop of the // UNDI interface! // PxeShutdown (Snp); PxeStop (Snp); // // Create EXIT_BOOT_SERIVES Event // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, SnpNotifyExitBootServices, Snp, &gEfiEventExitBootServicesGuid, &Snp->ExitBootServicesEvent ); if (EFI_ERROR (Status)) { goto Error_DeleteSNP; } // // add SNP to the undi handle // Status = gBS->InstallProtocolInterface ( &Controller, &gEfiSimpleNetworkProtocolGuid, EFI_NATIVE_INTERFACE, &(Snp->Snp) ); if (!EFI_ERROR (Status)) { return Status; } mPciIo->FreeBuffer ( mPciIo, SNP_MEM_PAGES (4096), Snp->Cpb ); Error_DeleteSNP: mPciIo->FreeBuffer ( mPciIo, SNP_MEM_PAGES (sizeof (SNP_DRIVER)), Snp ); NiiError: gBS->CloseProtocol ( Controller, &gEfiNetworkInterfaceIdentifierProtocolGuid_31, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); // // If we got here that means we are in error state. // if (!EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; } return Status; }
EFI_STATUS SimpleIioRootBridgeConstructor ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol, IN EFI_HANDLE HostBridgeHandle, IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture, UINT64 AllocAttributes ) /*++ Routine Description: Construct the Pci Root Bridge Io protocol. Arguments: Protocol - Protocol to initialize. HostBridgeHandle - Handle to the HostBridge. ResAperture - Resource apperture of the root bridge. AllocAttributes - Attribute of resouce allocated. Returns: EFI_SUCCESS - Success. Others - Fail. --*/ { EFI_STATUS Status; PCI_ROOT_BRIDGE_INSTANCE *PrivateData; PCI_RESOURCE_TYPE Index; UINT32 HecBase; UINT32 HecSize; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol); // // Initialize the apertures with default values // CopyMem ( &PrivateData->Aperture, ResAperture, sizeof (PCI_ROOT_BRIDGE_RESOURCE_APERTURE) ); for (Index = TypeIo; Index < TypeMax; Index++) { PrivateData->ResAllocNode[Index].Type = Index; PrivateData->ResAllocNode[Index].Base = 0; PrivateData->ResAllocNode[Index].Length = 0; PrivateData->ResAllocNode[Index].Status = ResNone; } EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL); PrivateData->PciAddress = 0xCF8; PrivateData->PciData = 0xCFC; PrivateData->RootBridgeAllocAttrib = AllocAttributes; PrivateData->Attributes = 0; PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_ATTRIBUTE_VGA_MEMORY | EFI_PCI_ATTRIBUTE_VGA_IO_16; // // Don't support BASE above 4GB currently // Position to bit 39:28 // HecBase = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressBase; HecSize = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressSize; ASSERT ((HecBase & (HecSize - 1)) == 0); ASSERT (HecBase != 0); PrivateData->HecBase = HecBase; PrivateData->HecLen = HecSize; PrivateData->BusNumberAssigned = FALSE; PrivateData->BusScanCount = 0; Protocol->ParentHandle = HostBridgeHandle; Protocol->PollMem = RootBridgeIoPollMem; Protocol->PollIo = RootBridgeIoPollIo; Protocol->Mem.Read = RootBridgeIoMemRead; Protocol->Mem.Write = RootBridgeIoMemWrite; Protocol->Io.Read = RootBridgeIoIoRead; Protocol->Io.Write = RootBridgeIoIoWrite; Protocol->CopyMem = RootBridgeIoCopyMem; Protocol->Pci.Read = RootBridgeIoPciRead; Protocol->Pci.Write = RootBridgeIoPciWrite; Protocol->Map = RootBridgeIoMap; Protocol->Unmap = RootBridgeIoUnmap; Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer; Protocol->FreeBuffer = RootBridgeIoFreeBuffer; Protocol->Flush = RootBridgeIoFlush; Protocol->GetAttributes = RootBridgeIoGetAttributes; Protocol->SetAttributes = RootBridgeIoSetAttributes; Protocol->Configuration = RootBridgeIoConfiguration; Protocol->SegmentNumber = 0; Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, &mMetronome); ASSERT_EFI_ERROR (Status); Status = gBS->LocateProtocol ( &gEfiCpuIoProtocolGuid, NULL, &mCpuIo ); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }
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; }
EFI_STATUS EFIAPI InitializePcatPciRootBridge ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) /*++ Routine Description: Initializes the PCI Root Bridge Controller Arguments: ImageHandle - SystemTable - Returns: None --*/ { EFI_STATUS Status; PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; UINTN PciSegmentIndex; UINTN PciRootBridgeIndex; UINTN PrimaryBusIndex; UINTN NumberOfPciRootBridges; UINTN NumberOfPciDevices; UINTN Device; UINTN Function; UINT16 VendorId; PCI_TYPE02 PciConfigurationHeader; UINT64 Address; UINT64 Value; UINT64 Base; UINT64 Limit; // // Initialize gCpuIo now since the chipset init code requires it. // Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&gCpuIo); ASSERT_EFI_ERROR (Status); // // Initialize variables required to search all PCI segments for PCI devices // PciSegmentIndex = 0; PciRootBridgeIndex = 0; NumberOfPciRootBridges = 0; PrimaryBusIndex = 0; while (PciSegmentIndex <= PCI_MAX_SEGMENT) { PrivateData = NULL; Status = gBS->AllocatePool( EfiBootServicesData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE), (VOID **)&PrivateData ); if (EFI_ERROR (Status)) { goto Done; } ZeroMem (PrivateData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE)); // // Initialize the signature of the private data structure // PrivateData->Signature = PCAT_PCI_ROOT_BRIDGE_SIGNATURE; PrivateData->Handle = NULL; PrivateData->DevicePath = NULL; InitializeListHead (&PrivateData->MapInfo); // // Initialize the PCI root bridge number and the bus range for that root bridge // PrivateData->RootBridgeNumber = (UINT32)PciRootBridgeIndex; PrivateData->PrimaryBus = (UINT32)PrimaryBusIndex; PrivateData->SubordinateBus = (UINT32)PrimaryBusIndex; PrivateData->IoBase = 0xffffffff; PrivateData->MemBase = 0xffffffff; PrivateData->Mem32Base = 0xffffffffffffffffULL; PrivateData->Pmem32Base = 0xffffffffffffffffULL; PrivateData->Mem64Base = 0xffffffffffffffffULL; PrivateData->Pmem64Base = 0xffffffffffffffffULL; // // The default mechanism for performing PCI Configuration cycles is to // use the I/O ports at 0xCF8 and 0xCFC. This is only used for IA-32. // IPF uses SAL calls to perform PCI COnfiguration cycles // PrivateData->PciAddress = 0xCF8; PrivateData->PciData = 0xCFC; // // Get the physical I/O base for performing PCI I/O cycles // For IA-32, this is always 0, because IA-32 has IN and OUT instructions // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles // Status = PcatRootBridgeIoGetIoPortMapping ( &PrivateData->PhysicalIoBase, &PrivateData->PhysicalMemoryBase ); if (EFI_ERROR (Status)) { goto Done; } // // Get PCI Express Base Address // PrivateData->PciExpressBaseAddress = GetPciExpressBaseAddressForRootBridge (PciSegmentIndex, PciRootBridgeIndex); /* if (PrivateData->PciExpressBaseAddress != 0) { DEBUG ((EFI_D_ERROR, "PCIE Base - 0x%lx\n", PrivateData->PciExpressBaseAddress)); } */ // // Create a lock for performing PCI Configuration cycles // EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL); // // Initialize the attributes for this PCI root bridge // PrivateData->Attributes = 0; // // Build the EFI Device Path Protocol instance for this PCI Root Bridge // Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (BOOLEAN)((PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE)); if (EFI_ERROR (Status)) { goto Done; } // // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge // Status = PcatRootBridgeIoConstructor (&PrivateData->Io, PciSegmentIndex); if (EFI_ERROR (Status)) { goto Done; } // // Scan all the PCI devices on the primary bus of the PCI root bridge // for (Device = 0, NumberOfPciDevices = 0; Device <= PCI_MAX_DEVICE; Device++) { for (Function = 0; Function <= PCI_MAX_FUNC; Function++) { // // Compute the PCI configuration address of the PCI device to probe // Address = EFI_PCI_ADDRESS (PrimaryBusIndex, Device, Function, 0); // // Read the Vendor ID from the PCI Configuration Header // Status = PrivateData->Io.Pci.Read ( &PrivateData->Io, EfiPciWidthUint16, Address, sizeof (VendorId) / sizeof (UINT16), &VendorId ); if ((EFI_ERROR (Status)) || ((VendorId == 0xffff) && (Function == 0))) { // // If the PCI Configuration Read fails, or a PCI device does not exist, then // skip this entire PCI device // break; } if (VendorId == 0xffff) { // // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function. // continue; } // // Read the entire PCI Configuration Header // Status = PrivateData->Io.Pci.Read ( &PrivateData->Io, EfiPciWidthUint16, Address, sizeof (PciConfigurationHeader) / sizeof (UINT16), &PciConfigurationHeader ); if (EFI_ERROR (Status)) { // // If the entire PCI Configuration Header can not be read, then skip this entire PCI device // break; } // // Increment the number of PCI device found on the primary bus of the PCI root bridge // NumberOfPciDevices++; // // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header // if (PciConfigurationHeader.Hdr.Command & 0x20) { PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; } // // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number // if (IS_PCI_BRIDGE(&PciConfigurationHeader)) { // // Get the Bus range that the PPB is decoding // if (PciConfigurationHeader.Bridge.P2PBridge.SubordinateBus > PrivateData->SubordinateBus) { // // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's // current subordinate bus number, then update the PCI root bridge's subordinate bus number // PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.P2PBridge.SubordinateBus; } // // Get the I/O range that the PPB is decoding // Value = PciConfigurationHeader.Bridge.P2PBridge.IoBase & 0x0f; Base = ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoBase & 0xf0) << 8; Limit = (((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoLimit & 0xf0) << 8) | 0x0fff; if (Value == 0x01) { Base |= ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoBaseUpper16 << 16); Limit |= ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoLimitUpper16 << 16); } if (Base < Limit) { if (PrivateData->IoBase > Base) { PrivateData->IoBase = Base; } if (PrivateData->IoLimit < Limit) { PrivateData->IoLimit = Limit; } } // // Get the Memory range that the PPB is decoding // Base = ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.MemoryBase & 0xfff0) << 16; Limit = (((UINT32)PciConfigurationHeader.Bridge.P2PBridge.MemoryLimit & 0xfff0) << 16) | 0xfffff; if (Base < Limit) { if (PrivateData->MemBase > Base) { PrivateData->MemBase = Base; } if (PrivateData->MemLimit < Limit) { PrivateData->MemLimit = Limit; } if (PrivateData->Mem32Base > Base) { PrivateData->Mem32Base = Base; } if (PrivateData->Mem32Limit < Limit) { PrivateData->Mem32Limit = Limit; } } // // Get the Prefetchable Memory range that the PPB is decoding // Value = PciConfigurationHeader.Bridge.P2PBridge.PrefetchableMemoryBase & 0x0f; Base = ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableMemoryBase & 0xfff0) << 16; Limit = (((UINT32)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff; if (Value == 0x01) { Base |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableBaseUpper32,32); Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableLimitUpper32,32); } if (Base < Limit) { if (PrivateData->MemBase > Base) { PrivateData->MemBase = Base; } if (PrivateData->MemLimit < Limit) { PrivateData->MemLimit = Limit; } if (Value == 0x00) { if (PrivateData->Pmem32Base > Base) { PrivateData->Pmem32Base = Base; } if (PrivateData->Pmem32Limit < Limit) { PrivateData->Pmem32Limit = Limit; } } if (Value == 0x01) { if (PrivateData->Pmem64Base > Base) { PrivateData->Pmem64Base = Base; } if (PrivateData->Pmem64Limit < Limit) { PrivateData->Pmem64Limit = Limit; } } } // // Look at the PPB Configuration for legacy decoding attributes // if (PciConfigurationHeader.Bridge.P2PBridge.BridgeControl & 0x04) { PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO; PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO; } if (PciConfigurationHeader.Bridge.P2PBridge.BridgeControl & 0x08) { // PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY; PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO; } } else if (IS_CARDBUS_BRIDGE(&PciConfigurationHeader)) { // // Get the Bus range that the PPB is decoding // if (PciConfigurationHeader.Bridge.CardBridge.SubordinateBusNumber > PrivateData->SubordinateBus) { // // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's // current subordinate bus number, then update the PCI root bridge's subordinate bus number // PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.CardBridge.SubordinateBusNumber; } // // Get the I/O range that the PPB is decoding // Base = PciConfigurationHeader.Bridge.CardBridge.IoBase0; Limit = PciConfigurationHeader.Bridge.CardBridge.IoLimit0; if (Base < Limit) { if (PrivateData->IoBase > Base) { PrivateData->IoBase = Base; } if (PrivateData->IoLimit < Limit) { PrivateData->IoLimit = Limit; } } // // Get the Memory range that the PPB is decoding // Base = PciConfigurationHeader.Bridge.CardBridge.MemoryBase0; Limit = PciConfigurationHeader.Bridge.CardBridge.MemoryLimit0; if (Base < Limit) { if (PrivateData->MemBase > Base) { PrivateData->MemBase = Base; } if (PrivateData->MemLimit < Limit) { PrivateData->MemLimit = Limit; } if (PrivateData->Mem32Base > Base) { PrivateData->Mem32Base = Base; } if (PrivateData->Mem32Limit < Limit) { PrivateData->Mem32Limit = Limit; } } } else { // // Parse the BARs of the PCI device to determine what I/O Ranges, // Memory Ranges, and Prefetchable Memory Ranges the device is decoding // if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) { Status = PcatPciRootBridgeParseBars ( PrivateData, PciConfigurationHeader.Hdr.Command, PrimaryBusIndex, Device, Function ); } // // See if the PCI device is an IDE controller // if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 && PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) { if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) { PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO; PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO; } if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) { PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO; } if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) { PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO; } } // // See if the PCI device is a legacy VGA controller // if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 && PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) { PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY; PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO; } // // See if the PCI device is a standard VGA controller // if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 && PciConfigurationHeader.Hdr.ClassCode[1] == 0x00 ) { PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY; PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO; } // // See if the PCI Device is a PCI - ISA or PCI - EISA // or ISA_POSITIVIE_DECODE Bridge device // if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) { if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 || PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 || PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) { PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO; PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO; if (PrivateData->MemBase > 0xa0000) { PrivateData->MemBase = 0xa0000; } if (PrivateData->MemLimit < 0xbffff) { PrivateData->MemLimit = 0xbffff; } } } } // // If this device is not a multi function device, then skip the rest of this PCI device // if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) { break; } } } // // After scanning all the PCI devices on the PCI root bridge's primary bus, update the // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate // bus number + 1. // PrimaryBusIndex = PrivateData->SubordinateBus + 1; // // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge // exists. // if (NumberOfPciDevices > 0) { // // Adjust the I/O range used for bounds checking for the legacy decoding attributed // if (PrivateData->Attributes & 0x7f) { PrivateData->IoBase = 0; if (PrivateData->IoLimit < 0xffff) { PrivateData->IoLimit = 0xffff; } } // // Adjust the Memory range used for bounds checking for the legacy decoding attributed // if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) { if (PrivateData->MemBase > 0xa0000) { PrivateData->MemBase = 0xa0000; } if (PrivateData->MemLimit < 0xbffff) { PrivateData->MemLimit = 0xbffff; } } // // Build ACPI descriptors for the resources on the PCI Root Bridge // Status = ConstructConfiguration(PrivateData); ASSERT_EFI_ERROR (Status); // // Create the handle for this PCI Root Bridge // Status = gBS->InstallMultipleProtocolInterfaces ( &PrivateData->Handle, &gEfiDevicePathProtocolGuid, PrivateData->DevicePath, &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io, NULL ); ASSERT_EFI_ERROR (Status); // // Contruct DeviceIoProtocol // Status = DeviceIoConstructor ( PrivateData->Handle, &PrivateData->Io, PrivateData->DevicePath, (UINT16)PrivateData->PrimaryBus, (UINT16)PrivateData->SubordinateBus ); ASSERT_EFI_ERROR (Status); #if 0 //patch by nms42 // // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table // Status = ScanPciRootBridgeForRoms(&PrivateData->Io); #endif // // Increment the index for the next PCI Root Bridge // PciRootBridgeIndex++; } else { // // If no PCI Root Bridges were found on the current PCI segment, then exit // if (NumberOfPciRootBridges == 0) { Status = EFI_SUCCESS; goto Done; } } // // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0 // Otherwise, the search is continued on the next PCI Root Bridge // if (PrimaryBusIndex > PCI_MAX_BUS) { PciSegmentIndex++; NumberOfPciRootBridges = 0; PrimaryBusIndex = 0; } else { NumberOfPciRootBridges++; } } return EFI_SUCCESS; Done: // // Clean up memory allocated for the PCI Root Bridge that was searched but not created. // if (PrivateData) { if (PrivateData->DevicePath) { gBS->FreePool(PrivateData->DevicePath); } gBS->FreePool (PrivateData); } // // If no PCI Root Bridges were discovered, then return the error condition from scanning the // first PCI Root Bridge // if (PciRootBridgeIndex == 0) { return Status; } return EFI_SUCCESS; }
EFI_STATUS RootBridgeConstructor ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol, IN EFI_HANDLE HostBridgeHandle, IN UINT64 Attri, IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE *ResAppeture ) /*++ Routine Description: Construct the Pci Root Bridge Io protocol Arguments: Protocol - protocol to initialize Returns: None --*/ { EFI_STATUS Status; PCI_ROOT_BRIDGE_INSTANCE *PrivateData; PCI_RESOURCE_TYPE Index; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol); // // The host to pci bridge, the host memory and io addresses are // direct mapped to pci addresses, so no need translate, set bases to 0. // PrivateData->MemBase = ResAppeture->MemBase; PrivateData->IoBase = ResAppeture->IoBase; // // The host bridge only supports 32bit addressing for memory // and standard IA32 16bit io // PrivateData->MemLimit = ResAppeture->MemLimit; PrivateData->IoLimit = ResAppeture->IoLimit; // // Bus Appeture for this Root Bridge (Possible Range) // PrivateData->BusBase = ResAppeture->BusBase; PrivateData->BusLimit = ResAppeture->BusLimit; // // Specific for this chipset // for (Index = TypeIo; Index < TypeMax; Index++) { PrivateData->ResAllocNode[Index].Type = Index; PrivateData->ResAllocNode[Index].Base = 0; PrivateData->ResAllocNode[Index].Length = 0; PrivateData->ResAllocNode[Index].Status = ResNone; } EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL); PrivateData->PciAddress = 0xCF8; PrivateData->PciData = 0xCFC; PrivateData->RootBridgeAttrib = Attri; PrivateData->Attributes = 0; PrivateData->Supports = 0; Protocol->ParentHandle = HostBridgeHandle; Protocol->PollMem = RootBridgeIoPollMem; Protocol->PollIo = RootBridgeIoPollIo; Protocol->Mem.Read = RootBridgeIoMemRead; Protocol->Mem.Write = RootBridgeIoMemWrite; Protocol->Io.Read = RootBridgeIoIoRead; Protocol->Io.Write = RootBridgeIoIoWrite; Protocol->CopyMem = RootBridgeIoCopyMem; Protocol->Pci.Read = RootBridgeIoPciRead; Protocol->Pci.Write = RootBridgeIoPciWrite; Protocol->Map = RootBridgeIoMap; Protocol->Unmap = RootBridgeIoUnmap; Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer; Protocol->FreeBuffer = RootBridgeIoFreeBuffer; Protocol->Flush = RootBridgeIoFlush; Protocol->GetAttributes = RootBridgeIoGetAttributes; Protocol->SetAttributes = RootBridgeIoSetAttributes; Protocol->Configuration = RootBridgeIoConfiguration; Protocol->SegmentNumber = 0; Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&mCpuIo); ASSERT_EFI_ERROR (Status); Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }
EFI_STATUS EFIAPI FvbInitialize ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) /*++ Routine Description: This function does common initialization for FVB services Arguments: Returns: **/ { EFI_STATUS Status; EFI_FW_VOL_INSTANCE *FwhInstance = NULL; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; EFI_DXE_SERVICES *DxeServices; EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; UINT32 BufferSize; EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; EFI_HANDLE FwbHandle; EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; EFI_DEVICE_PATH_PROTOCOL *TempFwbDevicePath; FV_DEVICE_PATH TempFvbDevicePathData; UINT32 MaxLbaSize; EFI_PHYSICAL_ADDRESS BaseAddress; UINT64 Length; UINTN NumOfBlocks; EFI_PEI_HOB_POINTERS FvHob; // // Get the DXE services table // DxeServices = gDS; // // Allocate runtime services data for global variable, which contains // the private data of all firmware volume block instances // Status = gBS->AllocatePool ( EfiRuntimeServicesData, sizeof (ESAL_FWB_GLOBAL), (VOID**) &mFvbModuleGlobal ); ASSERT_EFI_ERROR (Status); // // Calculate the total size for all firmware volume block instances // BufferSize = 0; FvHob.Raw = GetHobList (); while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) { BaseAddress = FvHob.FirmwareVolume->BaseAddress; Length = FvHob.FirmwareVolume->Length; // // Check if it is a "real" flash // Status = DxeServices->GetMemorySpaceDescriptor ( BaseAddress, &Descriptor ); if (EFI_ERROR (Status)) { break; } if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) { FvHob.Raw = GET_NEXT_HOB (FvHob); continue; } FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; Status = ValidateFvHeader (FwVolHeader); if (EFI_ERROR (Status)) { // // Get FvbInfo // Status = GetFvbInfo (Length, &FwVolHeader); if (EFI_ERROR (Status)) { FvHob.Raw = GET_NEXT_HOB (FvHob); continue; } } BufferSize += (sizeof (EFI_FW_VOL_INSTANCE) + FwVolHeader->HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER)); FvHob.Raw = GET_NEXT_HOB (FvHob); } // // Only need to allocate once. There is only one copy of physical memory for // the private data of each FV instance. But in virtual mode or in physical // mode, the address of the the physical memory may be different. // Status = gBS->AllocatePool ( EfiRuntimeServicesData, BufferSize, (VOID**) &mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] ); ASSERT_EFI_ERROR (Status); // // Make a virtual copy of the FvInstance pointer. // FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance; mFvbModuleGlobal->NumFv = 0; MaxLbaSize = 0; FvHob.Raw = GetHobList (); while (NULL != (FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw))) { BaseAddress = FvHob.FirmwareVolume->BaseAddress; Length = FvHob.FirmwareVolume->Length; // // Check if it is a "real" flash // Status = DxeServices->GetMemorySpaceDescriptor ( BaseAddress, &Descriptor ); if (EFI_ERROR (Status)) { break; } if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) { FvHob.Raw = GET_NEXT_HOB (FvHob); continue; } FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; Status = ValidateFvHeader (FwVolHeader); if (EFI_ERROR (Status)) { // // Get FvbInfo to provide in FwhInstance. // Status = GetFvbInfo (Length, &FwVolHeader); if (EFI_ERROR (Status)) { FvHob.Raw = GET_NEXT_HOB (FvHob); continue; } // // Write healthy FV header back. // CopyMem ( (VOID *) (UINTN) BaseAddress, (VOID *) FwVolHeader, FwVolHeader->HeaderLength ); } FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress; FwhInstance->FvBase[FVB_VIRTUAL] = (UINTN) BaseAddress; CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength); FwVolHeader = &(FwhInstance->VolumeHeader); EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL); NumOfBlocks = 0; for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { // // Get the maximum size of a block. The size will be used to allocate // buffer for Scratch space, the intermediate buffer for FVB extension // protocol // if (MaxLbaSize < PtrBlockMapEntry->Length) { MaxLbaSize = PtrBlockMapEntry->Length; } NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks; } // // The total number of blocks in the FV. // FwhInstance->NumOfBlocks = NumOfBlocks; // // Add a FVB Protocol Instance // Status = gBS->AllocatePool ( EfiRuntimeServicesData, sizeof (EFI_FW_VOL_BLOCK_DEVICE), (VOID**) &FvbDevice ); ASSERT_EFI_ERROR (Status); CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE)); FvbDevice->Instance = mFvbModuleGlobal->NumFv; mFvbModuleGlobal->NumFv++; // // Set up the devicepath // FvbDevice->DevicePath.MemMapDevPath.StartingAddress = BaseAddress; FvbDevice->DevicePath.MemMapDevPath.EndingAddress = BaseAddress + (FwVolHeader->FvLength - 1); // // Find a handle with a matching device path that has supports FW Block protocol // TempFwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &TempFvbDevicePathData; CopyMem (TempFwbDevicePath, &FvbDevice->DevicePath, sizeof (FV_DEVICE_PATH)); Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle); if (EFI_ERROR (Status)) { // // LocateDevicePath fails so install a new interface and device path // FwbHandle = NULL; Status = gBS->InstallMultipleProtocolInterfaces ( &FwbHandle, &gEfiFirmwareVolumeBlockProtocolGuid, &FvbDevice->FwVolBlockInstance, &gEfiDevicePathProtocolGuid, &FvbDevice->DevicePath, NULL ); ASSERT_EFI_ERROR (Status); } else if (IsDevicePathEnd (TempFwbDevicePath)) { // // Device allready exists, so reinstall the FVB protocol // Status = gBS->HandleProtocol ( FwbHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID**)&OldFwbInterface ); ASSERT_EFI_ERROR (Status); Status = gBS->ReinstallProtocolInterface ( FwbHandle, &gEfiFirmwareVolumeBlockProtocolGuid, OldFwbInterface, &FvbDevice->FwVolBlockInstance ); ASSERT_EFI_ERROR (Status); } else { // // There was a FVB protocol on an End Device Path node // ASSERT (FALSE); } FwhInstance = (EFI_FW_VOL_INSTANCE *) ( (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) ); FvHob.Raw = GET_NEXT_HOB (FvHob); } return EFI_SUCCESS; }