/** Cancels a previously set callback function for a particular PCD token number. @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. @param[in] TokenNumber The PCD token number. @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set. @retval EFI_SUCCESS The PCD service has successfully established a call event for the CallBackToken requested. @retval EFI_NOT_FOUND The PCD service could not find the referenced token number. **/ EFI_STATUS EFIAPI DxeUnRegisterCallBackOnSet ( IN CONST EFI_GUID *Guid, OPTIONAL IN UINTN TokenNumber, IN PCD_PROTOCOL_CALLBACK CallBackFunction ) { EFI_STATUS Status; if (CallBackFunction == NULL) { return EFI_INVALID_PARAMETER; } // // Aquire lock to prevent reentrance from TPL_CALLBACK level // EfiAcquireLock (&mPcdDatabaseLock); Status = DxeUnRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction); EfiReleaseLock (&mPcdDatabaseLock); return Status; }
VOID fsw_efi_ReleaseLock ( VOID ) { EfiReleaseLock (&fsw_efi_Lock); }
/** Add it to hot key database, register it to existing TxtInEx. New TxtInEx will be automatically registered with all the hot key in dababase @param KeyOption Input key option info. **/ EFI_STATUS BmProcessKeyOption ( IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOption ) { EFI_STATUS Status; EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx; EFI_HANDLE *Handles; UINTN HandleCount; UINTN HandleIndex; UINTN Index; BM_HOTKEY *Hotkey; UINTN KeyIndex; // // 16 is enough to enumerate all the possible combination of LEFT_XXX and RIGHT_XXX // UINT32 KeyShiftStates[16]; UINTN KeyShiftStateCount; if (KeyOption->KeyData.Options.InputKeyCount > mBmHotkeySupportCount) { return EFI_UNSUPPORTED; } KeyShiftStateCount = 0; BmGenerateKeyShiftState (0, KeyOption, EFI_SHIFT_STATE_VALID, KeyShiftStates, &KeyShiftStateCount); ASSERT (KeyShiftStateCount <= ARRAY_SIZE (KeyShiftStates)); EfiAcquireLock (&mBmHotkeyLock); Handles = BmGetActiveConsoleIn (&HandleCount); for (Index = 0; Index < KeyShiftStateCount; Index++) { Hotkey = AllocateZeroPool (sizeof (BM_HOTKEY)); ASSERT (Hotkey != NULL); Hotkey->Signature = BM_HOTKEY_SIGNATURE; Hotkey->BootOption = KeyOption->BootOption; Hotkey->IsContinue = (BOOLEAN) (KeyOption == mBmContinueKeyOption); Hotkey->CodeCount = (UINT8) KeyOption->KeyData.Options.InputKeyCount; for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) { CopyMem (&Hotkey->KeyData[KeyIndex].Key, &KeyOption->Keys[KeyIndex], sizeof (EFI_INPUT_KEY)); Hotkey->KeyData[KeyIndex].KeyState.KeyShiftState = KeyShiftStates[Index]; } InsertTailList (&mBmHotkeyList, &Hotkey->Link); for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx); ASSERT_EFI_ERROR (Status); BmRegisterHotkeyNotify (TxtInEx, Hotkey); } } if (Handles != NULL) { FreePool (Handles); } EfiReleaseLock (&mBmHotkeyLock); return EFI_SUCCESS; }
/** Add it to hot key database, register it to existing TxtInEx. new TxtInEx will be automatically registered with all the hot key in dababase **/ EFI_STATUS ProcessKeyOption ( IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOption ) { EFI_STATUS Status; EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx; EFI_HANDLE *Handles; UINTN HandleCount; UINTN HandleIndex; UINTN Index; HOTKEY *Hotkey; UINTN KeyIndex; // // 16 is enough to enumerate all the possible combination of LEFT_XXX and RIGHT_XXX // UINT32 KeyShiftStates[16]; UINTN KeyShiftStateCount; KeyShiftStateCount = 0; GenerateKeyShiftState (0, KeyOption, EFI_SHIFT_STATE_VALID, KeyShiftStates, &KeyShiftStateCount); ASSERT (KeyShiftStateCount <= sizeof (KeyShiftStates) / sizeof (KeyShiftStates[0])); EfiAcquireLock (&mHotkeyLock); for (Index = 0; Index < KeyShiftStateCount; Index++) { Hotkey = AllocateZeroPool (sizeof (HOTKEY)); ASSERT (Hotkey != NULL); Hotkey->Signature = HOTKEY_SIGNATURE; Hotkey->BootOption = KeyOption->BootOption; Hotkey->IsContinue = (BOOLEAN) (KeyOption == mContinueKeyOption); Hotkey->CodeCount = (UINT8) KEY_OPTION_INPUT_KEY_COUNT (KeyOption); for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) { CopyMem (&Hotkey->KeyData[KeyIndex].Key, &KeyOption->Keys[KeyIndex], sizeof (EFI_INPUT_KEY)); Hotkey->KeyData[KeyIndex].KeyState.KeyShiftState = KeyShiftStates[Index]; } InsertTailList (&mHotkeyList, &Hotkey->Link); gBS->LocateHandleBuffer ( ByProtocol, &gEfiSimpleTextInputExProtocolGuid, NULL, &HandleCount, &Handles ); for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx); ASSERT_EFI_ERROR (Status); RegisterHotkeyNotify (TxtInEx, Hotkey); } } EfiReleaseLock (&mHotkeyLock); return EFI_SUCCESS; }
/** Releases lock only at boot time. Simply returns at runtime. This is a temperary function which will be removed when EfiReleaseLock() in UefiLib can handle the call in UEFI Runtimer driver in RT phase. It calls EfiReleaseLock() at boot time and simply returns at runtime. @param Lock A pointer to the lock to release. **/ VOID ReleaseLockOnlyAtBootTime ( IN EFI_LOCK *Lock ) { if (!EfiAtRuntime ()) { EfiReleaseLock (Lock); } }
/** Callback function for SimpleTextInEx protocol install events @param Event the event that is signaled. @param Context not used here. **/ VOID EFIAPI TxtInExCallback ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; UINTN BufferSize; EFI_HANDLE Handle; EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx; LIST_ENTRY *Link; while (TRUE) { BufferSize = sizeof (EFI_HANDLE); Status = gBS->LocateHandle ( ByRegisterNotify, NULL, mTxtInExRegistration, &BufferSize, &Handle ); if (EFI_ERROR (Status)) { // // If no more notification events exist // return ; } Status = gBS->HandleProtocol ( Handle, &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx ); ASSERT_EFI_ERROR (Status); // // Register the hot key notification for the existing items in the list // EfiAcquireLock (&mHotkeyLock); for (Link = GetFirstNode (&mHotkeyList); !IsNull (&mHotkeyList, Link); Link = GetNextNode (&mHotkeyList, Link)) { RegisterHotkeyNotify (TxtInEx, HOTKEY_FROM_LINK (Link)); } EfiReleaseLock (&mHotkeyLock); } }
/** Stop the hotkey processing. **/ VOID EFIAPI StopHotkeyService ( IN EFI_EVENT Event, IN VOID *Context ) { LIST_ENTRY *Link; HOTKEY *Hotkey; DEBUG ((EFI_D_INFO, "[Bds]Stop Hotkey Service!\n")); gBS->CloseEvent (Event); EfiAcquireLock (&mHotkeyLock); for (Link = GetFirstNode (&mHotkeyList); !IsNull (&mHotkeyList, Link); ) { Hotkey = HOTKEY_FROM_LINK (Link); UnregisterHotkeyNotify (Hotkey); Link = RemoveEntryList (Link); FreePool (Hotkey); } EfiReleaseLock (&mHotkeyLock); }
VOID NtfsReleaseLock ( VOID ) /*++ Routine Description: Unlock the volume. Arguments: Null. Returns: None. --*/ { EfiReleaseLock (&NtfsFsLock); }
STATIC EFI_STATUS RootBridgeIoPciRW ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN BOOLEAN Write, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 UserAddress, IN UINTN Count, IN OUT VOID *UserBuffer ) /*++ Routine Description: Arguments: Returns: --*/ { PCI_CONFIG_ACCESS_CF8 Pci; PCI_CONFIG_ACCESS_CF8 PciAligned; UINT32 Stride; UINTN PciData; UINTN PciDataStride; PCI_ROOT_BRIDGE_INSTANCE *PrivateData; if (Width >= EfiPciWidthMaximum) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); ASSERT (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*)&UserAddress)->ExtendedRegister == 0x00); Stride = 1 << Width; Pci.Bits.Reg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register; Pci.Bits.Func = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Function; Pci.Bits.Dev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Device; Pci.Bits.Bus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Bus; Pci.Bits.Reserved = 0; Pci.Bits.Enable = 1; // // PCI Configure access are all 32-bit aligned, but by accessing the // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types // are possible on PCI. // // To read a byte of PCI configuration space you load 0xcf8 and // read 0xcfc, 0xcfd, 0xcfe, 0xcff // PciDataStride = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register & 0x03; while (Count) { PciAligned = Pci; PciAligned.Bits.Reg &= 0xfc; PciData = PrivateData->PciData + PciDataStride; EfiAcquireLock(&PrivateData->PciLock); This->Io.Write (This, EfiPciWidthUint32, \ PrivateData->PciAddress, 1, &PciAligned); if (Write) { This->Io.Write (This, Width, PciData, 1, UserBuffer); } else { This->Io.Read (This, Width, PciData, 1, UserBuffer); } EfiReleaseLock(&PrivateData->PciLock); UserBuffer = ((UINT8 *)UserBuffer) + Stride; PciDataStride = (PciDataStride + Stride) % 4; Count -= 1; // // Only increment the PCI address if Width is not a FIFO. // if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) { Pci.Bits.Reg += Stride; } } return EFI_SUCCESS; }
EFI_STATUS LibGetTime ( OUT EFI_TIME *Time, OUT EFI_TIME_CAPABILITIES *Capabilities ) { EFI_STATUS Status; RTC_REGISTER_B RegisterB; UINT8 Century; UINTN BufferSize; // // Check parameters for null pointer // if (Time == NULL) { return EFI_INVALID_PARAMETER; } // // Acquire RTC Lock to make access to RTC atomic // EfiAcquireLock (&mRtc.RtcLock); // // Wait for up to 0.1 seconds for the RTC to be updated // Status = RtcWaitToUpdate (100000); if (EFI_ERROR (Status)) { EfiReleaseLock (&mRtc.RtcLock); return Status; } // // Read Register B // RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B); // // Get the Time/Date/Daylight Savings values. // Time->Second = RtcRead (RTC_ADDRESS_SECONDS); Time->Minute = RtcRead (RTC_ADDRESS_MINUTES); Time->Hour = RtcRead (RTC_ADDRESS_HOURS); Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH); Time->Month = RtcRead (RTC_ADDRESS_MONTH); Time->Year = RtcRead (RTC_ADDRESS_YEAR); ConvertRtcTimeToEfiTime (Time, RegisterB); if (RtcTestCenturyRegister () == EFI_SUCCESS) { Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f)); } else { Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY)); } Time->Year = (UINT16) (Century * 100 + Time->Year); // // Release RTC Lock. // EfiReleaseLock (&mRtc.RtcLock); // // Get the variable that containts the TimeZone and Daylight fields // Time->TimeZone = mRtc.SavedTimeZone; Time->Daylight = mRtc.Daylight; BufferSize = sizeof (INT16) + sizeof (UINT8); // // Make sure all field values are in correct range // Status = RtcTimeFieldsValid (Time); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } // // Fill in Capabilities if it was passed in // if (Capabilities) { Capabilities->Resolution = 1; // // 1 hertz // Capabilities->Accuracy = 50000000; // // 50 ppm // Capabilities->SetsToZero = FALSE; } return EFI_SUCCESS; }
/** Update the string associated with an existing SMBIOS record. @param This The EFI_SMBIOS_PROTOCOL instance. @param SmbiosHandle SMBIOS Handle of structure that will have its string updated. @param StringNumber The non-zero string number of the string to update @param String Update the StringNumber string with String. @retval EFI_SUCCESS SmbiosHandle had its StringNumber String updated. @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. @retval EFI_UNSUPPORTED String was not added because it is longer than the SMBIOS Table supports. @retval EFI_NOT_FOUND The StringNumber.is not valid for this SMBIOS record. **/ EFI_STATUS EFIAPI SmbiosUpdateString ( IN CONST EFI_SMBIOS_PROTOCOL *This, IN EFI_SMBIOS_HANDLE *SmbiosHandle, IN UINTN *StringNumber, IN CHAR8 *String ) { UINTN InputStrLen; UINTN TargetStrLen; UINTN StrIndex; UINTN TargetStrOffset; UINTN NewEntrySize; CHAR8 *StrStart; VOID *Raw; LIST_ENTRY *Link; LIST_ENTRY *Head; EFI_STATUS Status; SMBIOS_INSTANCE *Private; EFI_SMBIOS_ENTRY *SmbiosEntry; EFI_SMBIOS_ENTRY *ResizedSmbiosEntry; EFI_SMBIOS_HANDLE MaxSmbiosHandle; EFI_SMBIOS_TABLE_HEADER *Record; EFI_SMBIOS_RECORD_HEADER *InternalRecord; // // Check args validity // GetMaxSmbiosHandle(This, &MaxSmbiosHandle); if (*SmbiosHandle > MaxSmbiosHandle) { return EFI_INVALID_PARAMETER; } if (String == NULL) { return EFI_ABORTED; } if (*StringNumber == 0) { return EFI_NOT_FOUND; } InputStrLen = AsciiStrLen(String); if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)) { if (InputStrLen > SMBIOS_STRING_MAX_LENGTH) { return EFI_UNSUPPORTED; } } else if (This->MajorVersion < 3) { // // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string. // However, the length of the entire structure table (including all strings) must be reported // in the Structure Table Length field of the SMBIOS Structure Table Entry Point, // which is a WORD field limited to 65,535 bytes. // if (InputStrLen > SMBIOS_TABLE_MAX_LENGTH) { return EFI_UNSUPPORTED; } } else { if (InputStrLen > SMBIOS_3_0_TABLE_MAX_LENGTH) { // // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes. // The input string length should not exceed 0xFFFFFFFF bytes. // return EFI_UNSUPPORTED; } } Private = SMBIOS_INSTANCE_FROM_THIS (This); // // Enter into critical section // Status = EfiAcquireLockOrFail (&Private->DataLock); if (EFI_ERROR (Status)) { return Status; } Head = &Private->DataListHead; for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) { SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link); Record = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1); if (Record->Handle == *SmbiosHandle) { // // Find out the specified SMBIOS record // if (*StringNumber > SmbiosEntry->RecordHeader->NumberOfStrings) { EfiReleaseLock (&Private->DataLock); return EFI_NOT_FOUND; } // // Point to unformed string section // StrStart = (CHAR8 *) Record + Record->Length; for (StrIndex = 1, TargetStrOffset = 0; StrIndex < *StringNumber; StrStart++, TargetStrOffset++) { // // A string ends in 00h // if (*StrStart == 0) { StrIndex++; } // // String section ends in double-null (0000h) // if (*StrStart == 0 && *(StrStart + 1) == 0) { EfiReleaseLock (&Private->DataLock); return EFI_NOT_FOUND; } } if (*StrStart == 0) { StrStart++; TargetStrOffset++; } // // Now we get the string target // TargetStrLen = AsciiStrLen(StrStart); if (InputStrLen == TargetStrLen) { AsciiStrCpyS(StrStart, TargetStrLen + 1, String); // // Some UEFI drivers (such as network) need some information in SMBIOS table. // Here we create SMBIOS table and publish it in // configuration table, so other UEFI drivers can get SMBIOS table from // configuration table without depending on PI SMBIOS protocol. // SmbiosTableConstruction (SmbiosEntry->Smbios32BitTable, SmbiosEntry->Smbios64BitTable); EfiReleaseLock (&Private->DataLock); return EFI_SUCCESS; } SmbiosEntry->Smbios32BitTable = FALSE; SmbiosEntry->Smbios64BitTable = FALSE; if ((This->MajorVersion < 0x3) || ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0))) { // // 32-bit table is produced, check the valid length. // if ((EntryPointStructure != NULL) && (EntryPointStructure->TableLength + InputStrLen - TargetStrLen > SMBIOS_TABLE_MAX_LENGTH)) { // // The length of the entire structure table (including all strings) must be reported // in the Structure Table Length field of the SMBIOS Structure Table Entry Point, // which is a WORD field limited to 65,535 bytes. // DEBUG ((EFI_D_INFO, "SmbiosUpdateString: Total length exceeds max 32-bit table length\n")); } else { DEBUG ((EFI_D_INFO, "SmbiosUpdateString: New smbios record add to 32-bit table\n")); SmbiosEntry->Smbios32BitTable = TRUE; } } if ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT1) == BIT1)) { // // 64-bit table is produced, check the valid length. // if ((Smbios30EntryPointStructure != NULL) && (Smbios30EntryPointStructure->TableMaximumSize + InputStrLen - TargetStrLen > SMBIOS_3_0_TABLE_MAX_LENGTH)) { DEBUG ((EFI_D_INFO, "SmbiosUpdateString: Total length exceeds max 64-bit table length\n")); } else { DEBUG ((EFI_D_INFO, "SmbiosUpdateString: New smbios record add to 64-bit table\n")); SmbiosEntry->Smbios64BitTable = TRUE; } } if ((!SmbiosEntry->Smbios32BitTable) && (!SmbiosEntry->Smbios64BitTable)) { EfiReleaseLock (&Private->DataLock); return EFI_UNSUPPORTED; } // // Original string buffer size is not exactly match input string length. // Re-allocate buffer is needed. // NewEntrySize = SmbiosEntry->RecordSize + InputStrLen - TargetStrLen; ResizedSmbiosEntry = AllocateZeroPool (NewEntrySize); if (ResizedSmbiosEntry == NULL) { EfiReleaseLock (&Private->DataLock); return EFI_OUT_OF_RESOURCES; } InternalRecord = (EFI_SMBIOS_RECORD_HEADER *) (ResizedSmbiosEntry + 1); Raw = (VOID *) (InternalRecord + 1); // // Build internal record Header // InternalRecord->Version = EFI_SMBIOS_RECORD_HEADER_VERSION; InternalRecord->HeaderSize = (UINT16) sizeof (EFI_SMBIOS_RECORD_HEADER); InternalRecord->RecordSize = SmbiosEntry->RecordHeader->RecordSize + InputStrLen - TargetStrLen; InternalRecord->ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle; InternalRecord->NumberOfStrings = SmbiosEntry->RecordHeader->NumberOfStrings; // // Copy SMBIOS structure and optional strings. // CopyMem (Raw, SmbiosEntry->RecordHeader + 1, Record->Length + TargetStrOffset); CopyMem ((VOID*)((UINTN)Raw + Record->Length + TargetStrOffset), String, InputStrLen + 1); CopyMem ((CHAR8*)((UINTN)Raw + Record->Length + TargetStrOffset + InputStrLen + 1), (CHAR8*)Record + Record->Length + TargetStrOffset + TargetStrLen + 1, SmbiosEntry->RecordHeader->RecordSize - sizeof (EFI_SMBIOS_RECORD_HEADER) - Record->Length - TargetStrOffset - TargetStrLen - 1); // // Insert new record // ResizedSmbiosEntry->Signature = EFI_SMBIOS_ENTRY_SIGNATURE; ResizedSmbiosEntry->RecordHeader = InternalRecord; ResizedSmbiosEntry->RecordSize = NewEntrySize; ResizedSmbiosEntry->Smbios32BitTable = SmbiosEntry->Smbios32BitTable; ResizedSmbiosEntry->Smbios64BitTable = SmbiosEntry->Smbios64BitTable; InsertTailList (Link->ForwardLink, &ResizedSmbiosEntry->Link); // // Remove old record // RemoveEntryList(Link); FreePool(SmbiosEntry); // // Some UEFI drivers (such as network) need some information in SMBIOS table. // Here we create SMBIOS table and publish it in // configuration table, so other UEFI drivers can get SMBIOS table from // configuration table without depending on PI SMBIOS protocol. // SmbiosTableConstruction (ResizedSmbiosEntry->Smbios32BitTable, ResizedSmbiosEntry->Smbios64BitTable); EfiReleaseLock (&Private->DataLock); return EFI_SUCCESS; } } EfiReleaseLock (&Private->DataLock); return EFI_INVALID_PARAMETER; }
/** Remove an SMBIOS record. @param This The EFI_SMBIOS_PROTOCOL instance. @param SmbiosHandle The handle of the SMBIOS record to remove. @retval EFI_SUCCESS SMBIOS record was removed. @retval EFI_INVALID_PARAMETER SmbiosHandle does not specify a valid SMBIOS record. **/ EFI_STATUS EFIAPI SmbiosRemove ( IN CONST EFI_SMBIOS_PROTOCOL *This, IN EFI_SMBIOS_HANDLE SmbiosHandle ) { LIST_ENTRY *Link; LIST_ENTRY *Head; EFI_STATUS Status; EFI_SMBIOS_HANDLE MaxSmbiosHandle; SMBIOS_INSTANCE *Private; EFI_SMBIOS_ENTRY *SmbiosEntry; SMBIOS_HANDLE_ENTRY *HandleEntry; EFI_SMBIOS_TABLE_HEADER *Record; // // Check args validity // GetMaxSmbiosHandle(This, &MaxSmbiosHandle); if (SmbiosHandle > MaxSmbiosHandle) { return EFI_INVALID_PARAMETER; } Private = SMBIOS_INSTANCE_FROM_THIS (This); // // Enter into critical section // Status = EfiAcquireLockOrFail (&Private->DataLock); if (EFI_ERROR (Status)) { return Status; } Head = &Private->DataListHead; for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) { SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link); Record = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1); if (Record->Handle == SmbiosHandle) { // // Remove specified smobios record from DataList // RemoveEntryList(Link); // // Remove this handle from AllocatedHandleList // Head = &Private->AllocatedHandleListHead; for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) { HandleEntry = SMBIOS_HANDLE_ENTRY_FROM_LINK(Link); if (HandleEntry->SmbiosHandle == SmbiosHandle) { RemoveEntryList(Link); FreePool(HandleEntry); break; } } // // Some UEFI drivers (such as network) need some information in SMBIOS table. // Here we create SMBIOS table and publish it in // configuration table, so other UEFI drivers can get SMBIOS table from // configuration table without depending on PI SMBIOS protocol. // if (SmbiosEntry->Smbios32BitTable) { DEBUG ((EFI_D_INFO, "SmbiosRemove: remove from 32-bit table\n")); } if (SmbiosEntry->Smbios64BitTable) { DEBUG ((EFI_D_INFO, "SmbiosRemove: remove from 64-bit table\n")); } // // Update the whole SMBIOS table again based on which table the removed SMBIOS record is in. // SmbiosTableConstruction (SmbiosEntry->Smbios32BitTable, SmbiosEntry->Smbios64BitTable); FreePool(SmbiosEntry); EfiReleaseLock (&Private->DataLock); return EFI_SUCCESS; } } // // Leave critical section // EfiReleaseLock (&Private->DataLock); return EFI_INVALID_PARAMETER; }
/** Remove an SMBIOS record. @param This The EFI_SMBIOS_PROTOCOL instance. @param SmbiosHandle The handle of the SMBIOS record to remove. @retval EFI_SUCCESS SMBIOS record was removed. @retval EFI_INVALID_PARAMETER SmbiosHandle does not specify a valid SMBIOS record. **/ EFI_STATUS EFIAPI SmbiosRemove ( IN CONST EFI_SMBIOS_PROTOCOL *This, IN EFI_SMBIOS_HANDLE SmbiosHandle ) { LIST_ENTRY *Link; LIST_ENTRY *Head; EFI_STATUS Status; EFI_SMBIOS_HANDLE MaxSmbiosHandle; SMBIOS_INSTANCE *Private; EFI_SMBIOS_ENTRY *SmbiosEntry; SMBIOS_HANDLE_ENTRY *HandleEntry; EFI_SMBIOS_TABLE_HEADER *Record; // // Check args validity // GetMaxSmbiosHandle(This, &MaxSmbiosHandle); if (SmbiosHandle > MaxSmbiosHandle) { return EFI_INVALID_PARAMETER; } Private = SMBIOS_INSTANCE_FROM_THIS (This); // // Enter into critical section // Status = EfiAcquireLockOrFail (&Private->DataLock); if (EFI_ERROR (Status)) { return Status; } Head = &Private->DataListHead; for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) { SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link); Record = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1); if (Record->Handle == SmbiosHandle) { // // Remove specified smobios record from DataList // RemoveEntryList(Link); FreePool(SmbiosEntry); // // Remove this handle from AllocatedHandleList // Head = &Private->AllocatedHandleListHead; for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) { HandleEntry = SMBIOS_HANDLE_ENTRY_FROM_LINK(Link); if (HandleEntry->SmbiosHandle == SmbiosHandle) { RemoveEntryList(Link); FreePool(HandleEntry); break; } } EfiReleaseLock (&Private->DataLock); return EFI_SUCCESS; } } // // Leave critical section // EfiReleaseLock (&Private->DataLock); return EFI_INVALID_PARAMETER; }
EFI_STATUS LibSetWakeupTime ( IN BOOLEAN Enabled, OUT EFI_TIME *Time ) { EFI_STATUS Status; EFI_TIME RtcTime; RTC_REGISTER_B RegisterB; UINT8 Century; EFI_TIME_CAPABILITIES Capabilities; if (Enabled) { if (Time == NULL) { return EFI_INVALID_PARAMETER; } // // Make sure that the time fields are valid // Status = RtcTimeFieldsValid (Time); if (EFI_ERROR (Status)) { return EFI_INVALID_PARAMETER; } // // Just support set alarm time within 24 hours // LibGetTime (&RtcTime, &Capabilities); if (Time->Year != RtcTime.Year || Time->Month != RtcTime.Month || (Time->Day != RtcTime.Day && Time->Day != (RtcTime.Day + 1)) ) { return EFI_UNSUPPORTED; } // // Make a local copy of the time and date // CopyMem (&RtcTime, Time, sizeof (EFI_TIME)); } // // Acquire RTC Lock to make access to RTC atomic // EfiAcquireLock (&mRtc.RtcLock); // // Wait for up to 0.1 seconds for the RTC to be updated // Status = RtcWaitToUpdate (100000); if (EFI_ERROR (Status)) { EfiReleaseLock (&mRtc.RtcLock); return EFI_DEVICE_ERROR; } // // Read Register B, and inhibit updates of the RTC // RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B); RegisterB.Bits.SET = 1; RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data); if (Enabled) { ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century); // // Set RTC alarm time // RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second); RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute); RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour); RegisterB.Bits.AIE = 1; } else { RegisterB.Bits.AIE = 0; } // // Allow updates of the RTC registers // RegisterB.Bits.SET = 0; RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data); // // Release RTC Lock. // EfiReleaseLock (&mRtc.RtcLock); return EFI_SUCCESS; }
EFI_STATUS LibSetTime ( IN EFI_TIME *Time ) { EFI_STATUS Status; EFI_TIME RtcTime; RTC_REGISTER_B RegisterB; UINT8 Century; if (Time == NULL) { return EFI_INVALID_PARAMETER; } // // Make sure that the time fields are valid // Status = RtcTimeFieldsValid (Time); if (EFI_ERROR (Status)) { return Status; } CopyMem (&RtcTime, Time, sizeof (EFI_TIME)); // // Acquire RTC Lock to make access to RTC atomic // EfiAcquireLock (&mRtc.RtcLock); // // Wait for up to 0.1 seconds for the RTC to be updated // Status = RtcWaitToUpdate (100000); if (EFI_ERROR (Status)) { EfiReleaseLock (&mRtc.RtcLock); return Status; } // // Read Register B, and inhibit updates of the RTC // RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B); RegisterB.Bits.SET = 1; RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data); ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century); RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second); RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute); RtcWrite (RTC_ADDRESS_HOURS, RtcTime.Hour); RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day); RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month); RtcWrite (RTC_ADDRESS_YEAR, (UINT8) RtcTime.Year); if (RtcTestCenturyRegister () == EFI_SUCCESS) { Century = (UINT8) ((Century & 0x7f) | (RtcRead (RTC_ADDRESS_CENTURY) & 0x80)); } RtcWrite (RTC_ADDRESS_CENTURY, Century); // // Allow updates of the RTC registers // RegisterB.Bits.SET = 0; RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data); // // Release RTC Lock. // EfiReleaseLock (&mRtc.RtcLock); // // Set the variable that containts the TimeZone and Daylight fields // mRtc.SavedTimeZone = Time->TimeZone; mRtc.Daylight = Time->Daylight; return Status; }
/** Add an SMBIOS record. @param This The EFI_SMBIOS_PROTOCOL instance. @param ProducerHandle The handle of the controller or driver associated with the SMBIOS information. NULL means no handle. @param SmbiosHandle On entry, if non-zero, the handle of the SMBIOS record. If zero, then a unique handle will be assigned to the SMBIOS record. If the SMBIOS handle is already in use EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated. @param Record The data for the fixed portion of the SMBIOS record. The format of the record is determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or a set of null terminated strings and a null. @retval EFI_SUCCESS Record was added. @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources. @retval EFI_ALREADY_STARTED The SmbiosHandle passed in was already in use. **/ EFI_STATUS EFIAPI SmbiosAdd ( IN CONST EFI_SMBIOS_PROTOCOL *This, IN EFI_HANDLE ProducerHandle, OPTIONAL IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle, IN EFI_SMBIOS_TABLE_HEADER *Record ) { VOID *Raw; UINTN TotalSize; UINTN RecordSize; UINTN StructureSize; UINTN NumberOfStrings; EFI_STATUS Status; LIST_ENTRY *Head; SMBIOS_INSTANCE *Private; EFI_SMBIOS_ENTRY *SmbiosEntry; EFI_SMBIOS_HANDLE MaxSmbiosHandle; SMBIOS_HANDLE_ENTRY *HandleEntry; EFI_SMBIOS_RECORD_HEADER *InternalRecord; if (SmbiosHandle == NULL) { return EFI_INVALID_PARAMETER; } Private = SMBIOS_INSTANCE_FROM_THIS (This); // // Check whether SmbiosHandle is already in use // Head = &Private->AllocatedHandleListHead; if (*SmbiosHandle != 0 && CheckSmbiosHandleExistance(Head, *SmbiosHandle)) { return EFI_ALREADY_STARTED; } // // when SmbiosHandle is zero, an available handle will be assigned // if (*SmbiosHandle == 0) { Status = GetAvailableSmbiosHandle(This, SmbiosHandle); if (EFI_ERROR(Status)) { return Status; } } else { // // Check this handle validity // GetMaxSmbiosHandle(This, &MaxSmbiosHandle); if (*SmbiosHandle > MaxSmbiosHandle) { return EFI_INVALID_PARAMETER; } } // // Calculate record size and string number // Status = GetSmbiosStructureSize(This, Record, &StructureSize, &NumberOfStrings); if (EFI_ERROR(Status)) { return Status; } // // Enter into critical section // Status = EfiAcquireLockOrFail (&Private->DataLock); if (EFI_ERROR (Status)) { return Status; } RecordSize = sizeof (EFI_SMBIOS_RECORD_HEADER) + StructureSize; TotalSize = sizeof (EFI_SMBIOS_ENTRY) + RecordSize; // // Allocate internal buffer // SmbiosEntry = AllocateZeroPool (TotalSize); if (SmbiosEntry == NULL) { EfiReleaseLock (&Private->DataLock); return EFI_OUT_OF_RESOURCES; } HandleEntry = AllocateZeroPool (sizeof(SMBIOS_HANDLE_ENTRY)); if (HandleEntry == NULL) { EfiReleaseLock (&Private->DataLock); return EFI_OUT_OF_RESOURCES; } // // Build Handle Entry and insert into linked list // HandleEntry->Signature = SMBIOS_HANDLE_ENTRY_SIGNATURE; HandleEntry->SmbiosHandle = *SmbiosHandle; InsertTailList(&Private->AllocatedHandleListHead, &HandleEntry->Link); InternalRecord = (EFI_SMBIOS_RECORD_HEADER *) (SmbiosEntry + 1); Raw = (VOID *) (InternalRecord + 1); // // Build internal record Header // InternalRecord->Version = EFI_SMBIOS_RECORD_HEADER_VERSION; InternalRecord->HeaderSize = (UINT16) sizeof (EFI_SMBIOS_RECORD_HEADER); InternalRecord->RecordSize = RecordSize; InternalRecord->ProducerHandle = ProducerHandle; InternalRecord->NumberOfStrings = NumberOfStrings; // // Insert record into the internal linked list // SmbiosEntry->Signature = EFI_SMBIOS_ENTRY_SIGNATURE; SmbiosEntry->RecordHeader = InternalRecord; SmbiosEntry->RecordSize = TotalSize; InsertTailList (&Private->DataListHead, &SmbiosEntry->Link); CopyMem (Raw, Record, StructureSize); ((EFI_SMBIOS_TABLE_HEADER*)Raw)->Handle = *SmbiosHandle; // // Leave critical section // EfiReleaseLock (&Private->DataLock); return EFI_SUCCESS; }
// // Internal function // EFI_STATUS RootBridgeIoPciRW ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN BOOLEAN Write, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 UserAddress, IN UINTN Count, IN OUT VOID *UserBuffer ) { PCI_CONFIG_ACCESS_CF8 Pci; PCI_CONFIG_ACCESS_CF8 PciAligned; UINT32 InStride; UINT32 OutStride; UINTN PciData; UINTN PciDataStride; PCI_ROOT_BRIDGE_INSTANCE *PrivateData; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress; if (Width < 0 || Width >= EfiPciWidthMaximum) { return EFI_INVALID_PARAMETER; } if ((Width & 0x03) >= EfiPciWidthUint64) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); InStride = 1 << (Width & 0x03); OutStride = InStride; if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) { InStride = 0; } if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) { OutStride = 0; } CopyMem (&PciAddress, &UserAddress, sizeof(UINT64)); if (PciAddress.ExtendedRegister > 0xFF) { return EFI_UNSUPPORTED; } if (PciAddress.ExtendedRegister != 0) { Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF; } else { Pci.Bits.Reg = PciAddress.Register; } Pci.Bits.Func = PciAddress.Function; Pci.Bits.Dev = PciAddress.Device; Pci.Bits.Bus = PciAddress.Bus; Pci.Bits.Reserved = 0; Pci.Bits.Enable = 1; // // PCI Config access are all 32-bit alligned, but by accessing the // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types // are possible on PCI. // // To read a byte of PCI config space you load 0xcf8 and // read 0xcfc, 0xcfd, 0xcfe, 0xcff // PciDataStride = Pci.Bits.Reg & 0x03; while (Count) { CopyMem (&PciAligned, &Pci, sizeof (PciAligned)); PciAligned.Bits.Reg &= 0xfc; PciData = (UINTN)PrivateData->PciData + PciDataStride; EfiAcquireLock(&PrivateData->PciLock); This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned); if (Write) { This->Io.Write (This, Width, PciData, 1, UserBuffer); } else { This->Io.Read (This, Width, PciData, 1, UserBuffer); } EfiReleaseLock(&PrivateData->PciLock); UserBuffer = ((UINT8 *)UserBuffer) + OutStride; PciDataStride = (PciDataStride + InStride) % 4; Pci.Bits.Reg += InStride; Count -= 1; } return EFI_SUCCESS; }
/** This is the common notification function for HotKeys, it will be registered with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle. @param KeyData A pointer to a buffer that is filled in with the keystroke information for the key that was pressed. @retval EFI_SUCCESS KeyData is successfully processed. @return EFI_NOT_FOUND Fail to find boot option variable. **/ EFI_STATUS EFIAPI HotkeyCallback ( IN EFI_KEY_DATA *KeyData ) { LIST_ENTRY *Link; HOTKEY *Hotkey; CHAR16 OptionName[sizeof ("Boot####")]; EFI_STATUS Status; EFI_KEY_DATA *HotkeyData; if (mHotkeyBootOption.OptionNumber != LoadOptionNumberUnassigned) { // // Do not process sequential hotkey stroke until the current boot option returns // return EFI_SUCCESS; } DEBUG ((EFI_D_INFO, "[Bds]HotkeyCallback: %04x:%04x\n", KeyData->Key.ScanCode, KeyData->Key.UnicodeChar)); EfiAcquireLock (&mHotkeyLock); for ( Link = GetFirstNode (&mHotkeyList) ; !IsNull (&mHotkeyList, Link) ; Link = GetNextNode (&mHotkeyList, Link) ) { Hotkey = HOTKEY_FROM_LINK (Link); // // Is this Key Stroke we are waiting for? // ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0]))); HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey]; if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) && (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) && (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE ) ) { // // Receive an expecting key stroke, transit to next waiting state // Hotkey->WaitingKey++; if (Hotkey->WaitingKey == Hotkey->CodeCount) { // // Reset to initial waiting state // Hotkey->WaitingKey = 0; // // Received the whole key stroke sequence // Status = gBS->SignalEvent (mHotkeyTriggered); ASSERT_EFI_ERROR (Status); if (!Hotkey->IsContinue) { // // Launch its BootOption // UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", Hotkey->BootOption); Status = EfiBootManagerVariableToLoadOption (OptionName, &mHotkeyBootOption); DEBUG ((EFI_D_INFO, "[Bds]Hotkey for %s pressed - %r\n", OptionName, Status)); if (EFI_ERROR (Status)) { mHotkeyBootOption.OptionNumber = LoadOptionNumberUnassigned; } } else { DEBUG ((EFI_D_INFO, "[Bds]Continue key pressed!\n")); } } } else { // // Receive an unexpected key stroke, reset to initial waiting state // Hotkey->WaitingKey = 0; } } EfiReleaseLock (&mHotkeyLock); return EFI_SUCCESS; }
// // ////////////////////////////////////////////////////////// // // BC Udp Read Routine // EFI_STATUS EFIAPI BcTcpRead ( IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN UINT16 OpFlags, IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL IN OUT EFI_PXE_BASE_CODE_TCP_PORT *DestPort, OPTIONAL IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL IN OUT EFI_PXE_BASE_CODE_TCP_PORT *SrcPort, OPTIONAL IN UINTN *HeaderSize, OPTIONAL IN VOID *HeaderPtr, OPTIONAL IN OUT UINTN *BufferSize, IN VOID *BufferPtr ) /*++ Routine description: TCP read API entry point. Parameters: This := Pointer to PxeBc interface OpFlags := DestIp := DestPort := SrcIp := SrcPort := HeaderSize := HeaderPtr := BufferSize := BufferPtr := Returns: EFI_SUCCESS := other := --*/ { EFI_STATUS StatCode; PXE_BASECODE_DEVICE *Private; // // Lock the instance data and make sure started // StatCode = EFI_SUCCESS; if (This == NULL) { DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); return EFI_INVALID_PARAMETER; } Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); if (Private == NULL) { DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); return EFI_INVALID_PARAMETER; } EfiAcquireLock (&Private->Lock); if (This->Mode == NULL || !This->Mode->Started) { DEBUG ((EFI_D_ERROR, "BC was not started.")); EfiReleaseLock (&Private->Lock); return EFI_NOT_STARTED; } Private->Function = EFI_PXE_BASE_CODE_FUNCTION_TCP_READ; // // Issue BC command // StatCode = TcpRead ( Private, OpFlags, DestIp, DestPort, SrcIp, SrcPort, HeaderSize, HeaderPtr, BufferSize, BufferPtr ); // // Unlock the instance data and return // EfiReleaseLock (&Private->Lock); return StatCode; }
// // ////////////////////////////////////////////////////////// // // BC Udp Write Routine // EFI_STATUS EFIAPI BcTcpWrite ( IN EFI_PXE_BASE_CODE_PROTOCOL *This, IN UINT16 OpFlags, IN UINT16 *UrgentPointer, IN UINT32 *SequenceNumber, IN UINT32 *AckNumber, IN UINT16 *HlenResCode, IN UINT16 *Window, IN EFI_IP_ADDRESS *DestIpPtr, IN EFI_PXE_BASE_CODE_TCP_PORT *DestPortPtr, IN EFI_IP_ADDRESS *GatewayIpPtr, OPTIONAL IN EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL IN OUT EFI_PXE_BASE_CODE_TCP_PORT *SrcPortPtr, OPTIONAL IN UINTN *HeaderSizePtr, OPTIONAL IN VOID *HeaderPtr, OPTIONAL IN UINTN *BufferSizePtr, IN VOID *BufferPtr ) /*++ Routine description: TCP write API entry point. Parameters: This := Pointer to PxeBc interface OpFlags := UrgentPointer := SequencePointer := AckNumber := HlenResCode := Window := DestIpPtr := DestPortPtr := GatewayIpPtr := SrcIpPtr := SrcPortPtr := HeaderSizePtr := HeaderPtr := BufferSizePtr := BufferPtr := Returns: EFI_SUCCESS := other := --*/ { EFI_STATUS StatCode; PXE_BASECODE_DEVICE *Private; // // Lock the instance data and make sure started // StatCode = EFI_SUCCESS; if (This == NULL) { DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); return EFI_INVALID_PARAMETER; } Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); if (Private == NULL) { DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); return EFI_INVALID_PARAMETER; } EfiAcquireLock (&Private->Lock); if (This->Mode == NULL || !This->Mode->Started) { DEBUG ((EFI_D_ERROR, "BC was not started.")); EfiReleaseLock (&Private->Lock); return EFI_NOT_STARTED; } Private->Function = EFI_PXE_BASE_CODE_FUNCTION_TCP_WRITE; // // Issue BC command // StatCode = TcpWrite ( Private, OpFlags, UrgentPointer, SequenceNumber, AckNumber, HlenResCode, Window, DestIpPtr, DestPortPtr, GatewayIpPtr, SrcIpPtr, SrcPortPtr, HeaderSizePtr, HeaderPtr, BufferSizePtr, BufferPtr ); // // Unlock the instance data // EfiReleaseLock (&Private->Lock); return StatCode; }
VOID LibRtcInitialize ( VOID ) { EFI_STATUS Status; RTC_REGISTER_A RegisterA; RTC_REGISTER_B RegisterB; RTC_REGISTER_C RegisterC; RTC_REGISTER_D RegisterD; UINT8 Century; EFI_TIME Time; // // Acquire RTC Lock to make access to RTC atomic // EfiAcquireLock (&mRtc.RtcLock); // // Initialize RTC Register // // Make sure Division Chain is properly configured, // or RTC clock won't "tick" -- time won't increment // RegisterA.Data = RTC_INIT_REGISTER_A; RtcWrite (RTC_ADDRESS_REGISTER_A, RegisterA.Data); // // Read Register B // RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B); // // Clear RTC flag register // RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C); // // Clear RTC register D // RegisterD.Data = RTC_INIT_REGISTER_D; RtcWrite (RTC_ADDRESS_REGISTER_D, RegisterD.Data); // // Wait for up to 0.1 seconds for the RTC to be updated // Status = RtcWaitToUpdate (100000); if (EFI_ERROR (Status)) { EfiReleaseLock (&mRtc.RtcLock); return; } // // Get the Time/Date/Daylight Savings values. // Time.Second = RtcRead (RTC_ADDRESS_SECONDS); Time.Minute = RtcRead (RTC_ADDRESS_MINUTES); Time.Hour = RtcRead (RTC_ADDRESS_HOURS); Time.Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH); Time.Month = RtcRead (RTC_ADDRESS_MONTH); Time.Year = RtcRead (RTC_ADDRESS_YEAR); ConvertRtcTimeToEfiTime (&Time, RegisterB); if (RtcTestCenturyRegister () == EFI_SUCCESS) { Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f)); } else { Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY)); } Time.Year = (UINT16) (Century * 100 + Time.Year); // // Set RTC configuration after get original time // RtcWrite (RTC_ADDRESS_REGISTER_B, RTC_INIT_REGISTER_B); // // Release RTC Lock. // EfiReleaseLock (&mRtc.RtcLock); // // Validate time fields // Status = RtcTimeFieldsValid (&Time); if (EFI_ERROR (Status)) { 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; } // // Reset time value according to new RTC configuration // LibSetTime (&Time); return; }
/** Log data record into the data logging hub @param This Protocol instance structure @param DataRecordGuid GUID that defines record contents @param ProducerName GUID that defines the name of the producer of the data @param DataRecordClass Class that defines generic record type @param RawData Data Log record as defined by DataRecordGuid @param RawDataSize Size of Data Log data in bytes @retval EFI_SUCCESS If data was logged @retval EFI_OUT_OF_RESOURCES If data was not logged due to lack of system resources. **/ EFI_STATUS EFIAPI DataHubLogData ( IN EFI_DATA_HUB_PROTOCOL *This, IN EFI_GUID *DataRecordGuid, IN EFI_GUID *ProducerName, IN UINT64 DataRecordClass, IN VOID *RawData, IN UINT32 RawDataSize ) { EFI_STATUS Status; DATA_HUB_INSTANCE *Private; EFI_DATA_ENTRY *LogEntry; UINT32 TotalSize; UINT32 RecordSize; EFI_DATA_RECORD_HEADER *Record; VOID *Raw; DATA_HUB_FILTER_DRIVER *FilterEntry; LIST_ENTRY *Link; LIST_ENTRY *Head; EFI_TIME LogTime; Private = DATA_HUB_INSTANCE_FROM_THIS (This); // // Combine the storage for the internal structs and a copy of the log record. // Record follows PrivateLogEntry. The consumer will be returned a pointer // to Record so we don't what it to be the thing that was allocated from // pool, so the consumer can't free an data record by mistake. // RecordSize = sizeof (EFI_DATA_RECORD_HEADER) + RawDataSize; TotalSize = sizeof (EFI_DATA_ENTRY) + RecordSize; // // First try to get log time at TPL level <= TPL_CALLBACK. // ZeroMem (&LogTime, sizeof (LogTime)); if (EfiGetCurrentTpl() <= TPL_CALLBACK) { gRT->GetTime (&LogTime, NULL); } // // The Logging action is the critical section, so it is locked. // The MTC asignment & update and logging must be an // atomic operation, so use the lock. // Status = EfiAcquireLockOrFail (&Private->DataLock); if (EFI_ERROR (Status)) { // // Reentrancy detected so exit! // return Status; } LogEntry = AllocatePool (TotalSize); if (LogEntry == NULL) { EfiReleaseLock (&Private->DataLock); return EFI_OUT_OF_RESOURCES; } ZeroMem (LogEntry, TotalSize); Record = (EFI_DATA_RECORD_HEADER *) (LogEntry + 1); Raw = (VOID *) (Record + 1); // // Build Standard Log Header // Record->Version = EFI_DATA_RECORD_HEADER_VERSION; Record->HeaderSize = (UINT16) sizeof (EFI_DATA_RECORD_HEADER); Record->RecordSize = RecordSize; CopyMem (&Record->DataRecordGuid, DataRecordGuid, sizeof (EFI_GUID)); CopyMem (&Record->ProducerName, ProducerName, sizeof (EFI_GUID)); Record->DataRecordClass = DataRecordClass; // // Ensure LogMonotonicCount is not zero // Record->LogMonotonicCount = ++Private->GlobalMonotonicCount; CopyMem (&Record->LogTime, &LogTime, sizeof (LogTime)); // // Insert log into the internal linked list. // LogEntry->Signature = EFI_DATA_ENTRY_SIGNATURE; LogEntry->Record = Record; LogEntry->RecordSize = sizeof (EFI_DATA_ENTRY) + RawDataSize; InsertTailList (&Private->DataListHead, &LogEntry->Link); CopyMem (Raw, RawData, RawDataSize); EfiReleaseLock (&Private->DataLock); // // Send Signal to all the filter drivers which are interested // in the record's class and guid. // Head = &Private->FilterDriverListHead; for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) { FilterEntry = FILTER_ENTRY_FROM_LINK (Link); if (((FilterEntry->ClassFilter & DataRecordClass) != 0) && (CompareGuid (&FilterEntry->FilterDataRecordGuid, &gZeroGuid) || CompareGuid (&FilterEntry->FilterDataRecordGuid, DataRecordGuid))) { gBS->SignalEvent (FilterEntry->Event); } } return EFI_SUCCESS; }
/** Starts the device with this driver. @param This The driver binding instance. @param Controller Handle of device to bind driver to. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS The controller is controlled by the driver. @retval Other This controller cannot be started. **/ EFI_STATUS EFIAPI BiosBlockIoDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; // EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; EFI_PCI_IO_PROTOCOL *PciIo; UINT8 DiskStart = 0x80; UINT8 DiskEnd = 0xFF; BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate; EFI_DEVICE_PATH_PROTOCOL *PciDevPath; UINTN Index; // UINTN Flags; UINTN TmpAddress; BOOLEAN DeviceEnable; // // Initialize variables // PciIo = NULL; PciDevPath = NULL; DeviceEnable = FALSE; // // See if the Legacy BIOS Protocol is available // /* Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); if (EFI_ERROR (Status)) { goto Error; } */ if (mLegacy8259 == NULL) { Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &mLegacy8259); if (EFI_ERROR (Status)) { goto Error; } InitializeBiosIntCaller(&mThunkContext); InitializeInterruptRedirection(mLegacy8259); } // // Open the IO Abstraction(s) needed // Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID **) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Error; } Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &PciDevPath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Error; } // // Enable the device and make sure VGA cycles are being forwarded to this VGA device // Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, EFI_PCI_DEVICE_ENABLE, NULL ); if (EFI_ERROR (Status)) { goto Error; } DeviceEnable = TRUE; // // Check to see if there is a legacy option ROM image associated with this PCI device // //Slice - something for replacement? /* Status = LegacyBios->CheckPciRom ( LegacyBios, Controller, NULL, NULL, &Flags ); if (EFI_ERROR (Status)) { goto Error; } // // Post the legacy option ROM if it is available. // Status = LegacyBios->InstallPciRom ( LegacyBios, Controller, NULL, &Flags, &DiskStart, &DiskEnd, NULL, NULL ); if (EFI_ERROR (Status)) { goto Error; } */ // // All instances share a buffer under 1MB to put real mode thunk code in // If it has not been allocated, then we allocate it. // if (mBufferUnder1Mb == 0) { // // Should only be here if there are no active instances // // ASSERT (mActiveInstances == 0); if (mActiveInstances) { Status = EFI_OUT_OF_RESOURCES; goto Error; } // // Acquire the lock // EfiAcquireLock (&mGlobalDataLock); // // Allocate below 1MB // mBufferUnder1Mb = 0x00000000000FFFFF; Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, BLOCK_IO_BUFFER_PAGE_SIZE, &mBufferUnder1Mb); // // Release the lock // EfiReleaseLock (&mGlobalDataLock); // // Check memory allocation success // if (EFI_ERROR (Status)) { // // In checked builds we want to assert if the allocate failed. // // ASSERT_EFI_ERROR (Status); Status = EFI_OUT_OF_RESOURCES; mBufferUnder1Mb = 0; goto Error; } TmpAddress = (UINTN) mBufferUnder1Mb; // // Adjusting the value to be on proper boundary // mEdd11Buffer = (VOID *) ALIGN_VARIABLE (TmpAddress); TmpAddress = (UINTN) mEdd11Buffer + MAX_EDD11_XFER; // // Adjusting the value to be on proper boundary // mLegacyDriverUnder1Mb = (BIOS_LEGACY_DRIVE *) ALIGN_VARIABLE (TmpAddress); TmpAddress = (UINTN) mLegacyDriverUnder1Mb + sizeof (BIOS_LEGACY_DRIVE); // // Adjusting the value to be on proper boundary // mEddBufferUnder1Mb = (EDD_DEVICE_ADDRESS_PACKET *) ALIGN_VARIABLE (TmpAddress); } // // Allocate the private device structure for each disk // for (Index = DiskStart; Index <= DiskEnd; Index++) { Status = gBS->AllocatePool ( EfiBootServicesData, sizeof (BIOS_BLOCK_IO_DEV), (VOID **) &BiosBlockIoPrivate ); if (EFI_ERROR (Status)) { goto Error; } // // Zero the private device structure // ZeroMem (BiosBlockIoPrivate, sizeof (BIOS_BLOCK_IO_DEV)); // // Initialize the private device structure // BiosBlockIoPrivate->Signature = BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE; BiosBlockIoPrivate->ControllerHandle = Controller; // BiosBlockIoPrivate->LegacyBios = LegacyBios; BiosBlockIoPrivate->Legacy8259 = mLegacy8259; BiosBlockIoPrivate->ThunkContext = &mThunkContext; BiosBlockIoPrivate->PciIo = PciIo; BiosBlockIoPrivate->Bios.Floppy = FALSE; BiosBlockIoPrivate->Bios.Number = (UINT8) Index; BiosBlockIoPrivate->Bios.Letter = (UINT8) (Index - 0x80 + 'C'); BiosBlockIoPrivate->BlockMedia.RemovableMedia = FALSE; if (BiosInitBlockIo (BiosBlockIoPrivate)) { SetBiosInitBlockIoDevicePath (PciDevPath, &BiosBlockIoPrivate->Bios, &BiosBlockIoPrivate->DevicePath); // // Install the Block Io Protocol onto a new child handle // Status = gBS->InstallMultipleProtocolInterfaces ( &BiosBlockIoPrivate->Handle, &gEfiBlockIoProtocolGuid, &BiosBlockIoPrivate->BlockIo, &gEfiDevicePathProtocolGuid, BiosBlockIoPrivate->DevicePath, NULL ); if (EFI_ERROR (Status)) { gBS->FreePool (BiosBlockIoPrivate); } // // Open For Child Device // Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID **) &BiosBlockIoPrivate->PciIo, This->DriverBindingHandle, BiosBlockIoPrivate->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); } else { gBS->FreePool (BiosBlockIoPrivate); } } mBiosDrivesEnumerated = TRUE; Error: if (EFI_ERROR (Status)) { if (PciIo != NULL) { if (DeviceEnable) { PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationDisable, EFI_PCI_DEVICE_ENABLE, NULL ); } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); if (PciDevPath != NULL) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); } if (mBufferUnder1Mb != 0 && mActiveInstances == 0) { gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE); // // Clear the buffer back to 0 // EfiAcquireLock (&mGlobalDataLock); mBufferUnder1Mb = 0; EfiReleaseLock (&mGlobalDataLock); } } } else { // // Successfully installed, so increment the number of active instances // EfiAcquireLock (&mGlobalDataLock); mActiveInstances++; EfiReleaseLock (&mGlobalDataLock); } return Status; }
/** Delete the Key Option variable and unregister the hot key **/ EFI_STATUS EFIAPI EfiBootManagerDeleteKeyOptionVariable ( IN EFI_BOOT_MANAGER_KEY_OPTION *DeletedOption, OPTIONAL IN UINT32 Modifier, ... ) { EFI_STATUS Status; UINTN Index; VA_LIST Args; EFI_BOOT_MANAGER_KEY_OPTION KeyOption; EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions; UINTN KeyOptionCount; LIST_ENTRY *Link; HOTKEY *Hotkey; UINT32 ShiftState; BOOLEAN Match; CHAR16 KeyOptionName[sizeof (L"Key####")]; ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION)); VA_START (Args, Modifier); Status = InitializeKeyFields (Modifier, Args, &KeyOption); VA_END (Args); if (EFI_ERROR (Status)) { return Status; } EfiAcquireLock (&mHotkeyLock); // // Delete the key option from active hot key list // Could have multiple entries when modifier isn't 0 because we map the ShiftPressed to RIGHT_SHIFT and RIGHT_SHIFT // for (Link = GetFirstNode (&mHotkeyList); !IsNull (&mHotkeyList, Link); ) { Hotkey = HOTKEY_FROM_LINK (Link); Match = (BOOLEAN) (Hotkey->CodeCount == KEY_OPTION_INPUT_KEY_COUNT (&KeyOption)); for (Index = 0; Match && (Index < Hotkey->CodeCount); Index++) { ShiftState = Hotkey->KeyData[Index].KeyState.KeyShiftState; if ( (BitSet (ShiftState, EFI_RIGHT_SHIFT_PRESSED | EFI_LEFT_SHIFT_PRESSED) != KEY_OPTION_SHIFT_PRESSED (&KeyOption)) || (BitSet (ShiftState, EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED) != KEY_OPTION_CONTROL_PRESSED (&KeyOption)) || (BitSet (ShiftState, EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED) != KEY_OPTION_ALT_PRESSED (&KeyOption)) || (BitSet (ShiftState, EFI_RIGHT_LOGO_PRESSED | EFI_LEFT_LOGO_PRESSED) != KEY_OPTION_LOGO_PRESSED (&KeyOption)) || (BitSet (ShiftState, EFI_MENU_KEY_PRESSED) != KEY_OPTION_MENU_PRESSED (&KeyOption)) || (BitSet (ShiftState, EFI_SYS_REQ_PRESSED) != KEY_OPTION_SYS_REQ_PRESSED (&KeyOption)) || (CompareMem (&Hotkey->KeyData[Index].Key, &KeyOption.Keys[Index], sizeof (EFI_INPUT_KEY)) != 0) ) { // // Break when any field doesn't match // Match = FALSE; break; } } if (Match) { Link = RemoveEntryList (Link); FreePool (Hotkey); } else { Link = GetNextNode (&mHotkeyList, Link); } } // // Delete the key option from the variable // Status = EFI_NOT_FOUND; KeyOptions = EfiBootManagerGetKeyOptions (&KeyOptionCount); for (Index = 0; Index < KeyOptionCount; Index++) { if ((KeyOptions[Index].KeyData == KeyOption.KeyData) && (CompareMem ( KeyOptions[Index].Keys, KeyOption.Keys, KEY_OPTION_INPUT_KEY_COUNT (&KeyOption)* sizeof (EFI_INPUT_KEY)) == 0) ) { UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptions[Index].OptionNumber); Status = gRT->SetVariable ( KeyOptionName, &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, 0, NULL ); // // Return the deleted key option in case needed by caller // if (DeletedOption != NULL) { CopyMem (DeletedOption, &KeyOptions[Index], sizeof (EFI_BOOT_MANAGER_KEY_OPTION)); } break; } } EfiBootManagerFreeKeyOptions (KeyOptions, KeyOptionCount); EfiReleaseLock (&mHotkeyLock); return Status; }
/** Stop the device handled by this driver. @param This The driver binding protocol. @param Controller The controller to release. @param NumberOfChildren The number of handles in ChildHandleBuffer. @param ChildHandleBuffer The array of child handle. @retval EFI_SUCCESS The device was stopped. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. @retval Others Fail to uninstall protocols attached on the device. **/ EFI_STATUS EFIAPI BiosBlockIoDriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; BOOLEAN AllChildrenStopped; EFI_BLOCK_IO_PROTOCOL *BlockIo; BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate; UINTN Index; // // Decrement the number of active instances // if (mActiveInstances != 0) { // // Add a check since the stop function will be called 2 times for each handle // EfiAcquireLock (&mGlobalDataLock); mActiveInstances--; EfiReleaseLock (&mGlobalDataLock); } if ((mActiveInstances == 0) && (mBufferUnder1Mb != 0)) { // // Free our global buffer // Status = gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE); // ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { return Status; } EfiAcquireLock (&mGlobalDataLock); mBufferUnder1Mb = 0; EfiReleaseLock (&mGlobalDataLock); } AllChildrenStopped = TRUE; for (Index = 0; Index < NumberOfChildren; Index++) { Status = gBS->OpenProtocol ( ChildHandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } BiosBlockIoPrivate = BIOS_BLOCK_IO_FROM_THIS (BlockIo); // // Release PCI I/O and Block IO Protocols on the clild handle. // Status = gBS->UninstallMultipleProtocolInterfaces ( ChildHandleBuffer[Index], &gEfiBlockIoProtocolGuid, &BiosBlockIoPrivate->BlockIo, &gEfiDevicePathProtocolGuid, BiosBlockIoPrivate->DevicePath, NULL ); if (EFI_ERROR (Status)) { AllChildrenStopped = FALSE; } // // Shutdown the hardware // BiosBlockIoPrivate->PciIo->Attributes ( BiosBlockIoPrivate->PciIo, EfiPciIoAttributeOperationDisable, EFI_PCI_DEVICE_ENABLE, NULL ); gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, ChildHandleBuffer[Index] ); gBS->FreePool (BiosBlockIoPrivate); } if (!AllChildrenStopped) { return EFI_DEVICE_ERROR; } /*Status = */gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); /*Status = */gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); return EFI_SUCCESS; }
/** Update the string associated with an existing SMBIOS record. @param This The EFI_SMBIOS_PROTOCOL instance. @param SmbiosHandle SMBIOS Handle of structure that will have its string updated. @param StringNumber The non-zero string number of the string to update @param String Update the StringNumber string with String. @retval EFI_SUCCESS SmbiosHandle had its StringNumber String updated. @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. @retval EFI_UNSUPPORTED String was not added since it's longer than 64 significant characters. @retval EFI_NOT_FOUND The StringNumber.is not valid for this SMBIOS record. **/ EFI_STATUS EFIAPI SmbiosUpdateString ( IN CONST EFI_SMBIOS_PROTOCOL *This, IN EFI_SMBIOS_HANDLE *SmbiosHandle, IN UINTN *StringNumber, IN CHAR8 *String ) { UINTN InputStrLen; UINTN TargetStrLen; UINTN StrIndex; UINTN TargetStrOffset; UINTN NewEntrySize; CHAR8 *StrStart; VOID *Raw; LIST_ENTRY *Link; LIST_ENTRY *Head; EFI_STATUS Status; SMBIOS_INSTANCE *Private; EFI_SMBIOS_ENTRY *SmbiosEntry; EFI_SMBIOS_ENTRY *ResizedSmbiosEntry; EFI_SMBIOS_HANDLE MaxSmbiosHandle; EFI_SMBIOS_TABLE_HEADER *Record; EFI_SMBIOS_RECORD_HEADER *InternalRecord; // // Check args validity // GetMaxSmbiosHandle(This, &MaxSmbiosHandle); if (*SmbiosHandle > MaxSmbiosHandle) { return EFI_INVALID_PARAMETER; } if (String == NULL) { return EFI_ABORTED; } if (*StringNumber == 0) { //Slice - there should be a way to add a string if not exists return EFI_NOT_FOUND; } InputStrLen = AsciiStrLen(String); // // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string // if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)) { if (InputStrLen > SMBIOS_STRING_MAX_LENGTH) { return EFI_UNSUPPORTED; } } Private = SMBIOS_INSTANCE_FROM_THIS (This); // // Enter into critical section // Status = EfiAcquireLockOrFail (&Private->DataLock); if (EFI_ERROR (Status)) { return Status; } Head = &Private->DataListHead; for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) { SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link); Record = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1); if (Record->Handle == *SmbiosHandle) { // // Find out the specified Smbios record // if (*StringNumber > SmbiosEntry->RecordHeader->NumberOfStrings) { EfiReleaseLock (&Private->DataLock); return EFI_NOT_FOUND; } // // Point to unformed string section // StrStart = (CHAR8 *) Record + Record->Length; for (StrIndex = 1, TargetStrOffset = 0; StrIndex < *StringNumber; StrStart++, TargetStrOffset++) { // // A string ends in 00h // if (*StrStart == 0) { StrIndex++; } // // String section ends in double-null (0000h) // if (*StrStart == 0 && *(StrStart + 1) == 0) { EfiReleaseLock (&Private->DataLock); return EFI_NOT_FOUND; } } if (*StrStart == 0) { StrStart++; TargetStrOffset++; } // // Now we get the string target // TargetStrLen = AsciiStrLen(StrStart); if (InputStrLen == TargetStrLen) { AsciiStrCpy(StrStart, String); EfiReleaseLock (&Private->DataLock); return EFI_SUCCESS; } // // Original string buffer size is not exactly match input string length. // Re-allocate buffer is needed. // NewEntrySize = SmbiosEntry->RecordSize + InputStrLen - TargetStrLen; ResizedSmbiosEntry = AllocateZeroPool (NewEntrySize); if (ResizedSmbiosEntry == NULL) { EfiReleaseLock (&Private->DataLock); return EFI_OUT_OF_RESOURCES; } InternalRecord = (EFI_SMBIOS_RECORD_HEADER *) (ResizedSmbiosEntry + 1); Raw = (VOID *) (InternalRecord + 1); // // Build internal record Header // InternalRecord->Version = EFI_SMBIOS_RECORD_HEADER_VERSION; InternalRecord->HeaderSize = (UINT16) sizeof (EFI_SMBIOS_RECORD_HEADER); InternalRecord->RecordSize = SmbiosEntry->RecordHeader->RecordSize + InputStrLen - TargetStrLen; InternalRecord->ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle; InternalRecord->NumberOfStrings = SmbiosEntry->RecordHeader->NumberOfStrings; // // Copy smbios structure and optional strings. // CopyMem (Raw, SmbiosEntry->RecordHeader + 1, Record->Length + TargetStrOffset); CopyMem ((VOID*)((UINTN)Raw + Record->Length + TargetStrOffset), String, InputStrLen + 1); CopyMem ((CHAR8*)((UINTN)Raw + Record->Length + TargetStrOffset + InputStrLen + 1), (CHAR8*)Record + Record->Length + TargetStrOffset + TargetStrLen + 1, SmbiosEntry->RecordHeader->RecordSize - sizeof (EFI_SMBIOS_RECORD_HEADER) - Record->Length - TargetStrOffset - TargetStrLen - 1); // // Insert new record // ResizedSmbiosEntry->Signature = EFI_SMBIOS_ENTRY_SIGNATURE; ResizedSmbiosEntry->RecordHeader = InternalRecord; ResizedSmbiosEntry->RecordSize = NewEntrySize; InsertTailList (Link->ForwardLink, &ResizedSmbiosEntry->Link); // // Remove old record // RemoveEntryList(Link); FreePool(SmbiosEntry); EfiReleaseLock (&Private->DataLock); return EFI_SUCCESS; } } EfiReleaseLock (&Private->DataLock); return EFI_INVALID_PARAMETER; }
/** Add an SMBIOS record. @param This The EFI_SMBIOS_PROTOCOL instance. @param ProducerHandle The handle of the controller or driver associated with the SMBIOS information. NULL means no handle. @param SmbiosHandle On entry, the handle of the SMBIOS record to add. If FFFEh, then a unique handle will be assigned to the SMBIOS record. If the SMBIOS handle is already in use, EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated. @param Record The data for the fixed portion of the SMBIOS record. The format of the record is determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or a set of null terminated strings and a null. @retval EFI_SUCCESS Record was added. @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources. @retval EFI_ALREADY_STARTED The SmbiosHandle passed in was already in use. **/ EFI_STATUS EFIAPI SmbiosAdd ( IN CONST EFI_SMBIOS_PROTOCOL *This, IN EFI_HANDLE ProducerHandle, OPTIONAL IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle, IN EFI_SMBIOS_TABLE_HEADER *Record ) { VOID *Raw; UINTN TotalSize; UINTN RecordSize; UINTN StructureSize; UINTN NumberOfStrings; EFI_STATUS Status; LIST_ENTRY *Head; SMBIOS_INSTANCE *Private; EFI_SMBIOS_ENTRY *SmbiosEntry; EFI_SMBIOS_HANDLE MaxSmbiosHandle; SMBIOS_HANDLE_ENTRY *HandleEntry; EFI_SMBIOS_RECORD_HEADER *InternalRecord; BOOLEAN Smbios32BitTable; BOOLEAN Smbios64BitTable; if (SmbiosHandle == NULL) { return EFI_INVALID_PARAMETER; } Private = SMBIOS_INSTANCE_FROM_THIS (This); // // Check whether SmbiosHandle is already in use // Head = &Private->AllocatedHandleListHead; if (*SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED && CheckSmbiosHandleExistance(Head, *SmbiosHandle)) { return EFI_ALREADY_STARTED; } // // when SmbiosHandle is 0xFFFE, an available handle will be assigned // if (*SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) { Status = GetAvailableSmbiosHandle(This, SmbiosHandle); if (EFI_ERROR(Status)) { return Status; } } else { // // Check this handle validity // GetMaxSmbiosHandle(This, &MaxSmbiosHandle); if (*SmbiosHandle > MaxSmbiosHandle) { return EFI_INVALID_PARAMETER; } } // // Calculate record size and string number // Status = GetSmbiosStructureSize(This, Record, &StructureSize, &NumberOfStrings); if (EFI_ERROR(Status)) { return Status; } Smbios32BitTable = FALSE; Smbios64BitTable = FALSE; if ((This->MajorVersion < 0x3) || ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0))) { // // For SMBIOS 32-bit table, the length of the entire structure table (including all strings) must be reported // in the Structure Table Length field of the SMBIOS Structure Table Entry Point, // which is a WORD field limited to 65,535 bytes. So the max size of 32-bit table should not exceed 65,535 bytes. // if ((EntryPointStructure != NULL) && (EntryPointStructure->TableLength + StructureSize > SMBIOS_TABLE_MAX_LENGTH)) { DEBUG ((EFI_D_INFO, "SmbiosAdd: Total length exceeds max 32-bit table length with type = %d size = 0x%x\n", Record->Type, StructureSize)); } else { Smbios32BitTable = TRUE; DEBUG ((EFI_D_INFO, "SmbiosAdd: Smbios type %d with size 0x%x is added to 32-bit table\n", Record->Type, StructureSize)); } } // // For SMBIOS 3.0, Structure table maximum size in Entry Point structure is DWORD field limited to 0xFFFFFFFF bytes. // if ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT1) == BIT1)) { // // For SMBIOS 64-bit table, Structure table maximum size in SMBIOS 3.0 (64-bit) Entry Point // is a DWORD field limited to 0xFFFFFFFF bytes. So the max size of 64-bit table should not exceed 0xFFFFFFFF bytes. // if ((Smbios30EntryPointStructure != NULL) && (Smbios30EntryPointStructure->TableMaximumSize + StructureSize > SMBIOS_3_0_TABLE_MAX_LENGTH)) { DEBUG ((EFI_D_INFO, "SmbiosAdd: Total length exceeds max 64-bit table length with type = %d size = 0x%x\n", Record->Type, StructureSize)); } else { DEBUG ((EFI_D_INFO, "SmbiosAdd: Smbios type %d with size 0x%x is added to 64-bit table\n", Record->Type, StructureSize)); Smbios64BitTable = TRUE; } } if ((!Smbios32BitTable) && (!Smbios64BitTable)) { // // If both 32-bit and 64-bit table are not updated, quit // return EFI_OUT_OF_RESOURCES; } // // Enter into critical section // Status = EfiAcquireLockOrFail (&Private->DataLock); if (EFI_ERROR (Status)) { return Status; } RecordSize = sizeof (EFI_SMBIOS_RECORD_HEADER) + StructureSize; TotalSize = sizeof (EFI_SMBIOS_ENTRY) + RecordSize; // // Allocate internal buffer // SmbiosEntry = AllocateZeroPool (TotalSize); if (SmbiosEntry == NULL) { EfiReleaseLock (&Private->DataLock); return EFI_OUT_OF_RESOURCES; } HandleEntry = AllocateZeroPool (sizeof(SMBIOS_HANDLE_ENTRY)); if (HandleEntry == NULL) { EfiReleaseLock (&Private->DataLock); return EFI_OUT_OF_RESOURCES; } // // Build Handle Entry and insert into linked list // HandleEntry->Signature = SMBIOS_HANDLE_ENTRY_SIGNATURE; HandleEntry->SmbiosHandle = *SmbiosHandle; InsertTailList(&Private->AllocatedHandleListHead, &HandleEntry->Link); InternalRecord = (EFI_SMBIOS_RECORD_HEADER *) (SmbiosEntry + 1); Raw = (VOID *) (InternalRecord + 1); // // Build internal record Header // InternalRecord->Version = EFI_SMBIOS_RECORD_HEADER_VERSION; InternalRecord->HeaderSize = (UINT16) sizeof (EFI_SMBIOS_RECORD_HEADER); InternalRecord->RecordSize = RecordSize; InternalRecord->ProducerHandle = ProducerHandle; InternalRecord->NumberOfStrings = NumberOfStrings; // // Insert record into the internal linked list // SmbiosEntry->Signature = EFI_SMBIOS_ENTRY_SIGNATURE; SmbiosEntry->RecordHeader = InternalRecord; SmbiosEntry->RecordSize = TotalSize; SmbiosEntry->Smbios32BitTable = Smbios32BitTable; SmbiosEntry->Smbios64BitTable = Smbios64BitTable; InsertTailList (&Private->DataListHead, &SmbiosEntry->Link); CopyMem (Raw, Record, StructureSize); ((EFI_SMBIOS_TABLE_HEADER*)Raw)->Handle = *SmbiosHandle; // // Some UEFI drivers (such as network) need some information in SMBIOS table. // Here we create SMBIOS table and publish it in // configuration table, so other UEFI drivers can get SMBIOS table from // configuration table without depending on PI SMBIOS protocol. // SmbiosTableConstruction (Smbios32BitTable, Smbios64BitTable); // // Leave critical section // EfiReleaseLock (&Private->DataLock); return EFI_SUCCESS; }
EFI_STATUS PcatRootBridgeIoPciRW ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN BOOLEAN Write, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 UserAddress, IN UINTN Count, IN OUT VOID *UserBuffer ) { PCI_CONFIG_ACCESS_CF8 Pci; PCI_CONFIG_ACCESS_CF8 PciAligned; UINT32 InStride; UINT32 OutStride; UINTN PciData; UINTN PciDataStride; PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress; UINT64 PciExpressRegAddr; BOOLEAN UsePciExpressAccess; if (Width < 0 || Width >= EfiPciWidthMaximum) { return EFI_INVALID_PARAMETER; } if ((Width & 0x03) >= EfiPciWidthUint64) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); InStride = 1 << (Width & 0x03); OutStride = InStride; if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { InStride = 0; } if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) { OutStride = 0; } UsePciExpressAccess = FALSE; CopyMem (&PciAddress, &UserAddress, sizeof(UINT64)); if (PciAddress.ExtendedRegister > 0xFF) { // // Check PciExpressBaseAddress // if ((PrivateData->PciExpressBaseAddress == 0) || (PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) { return EFI_UNSUPPORTED; } else { UsePciExpressAccess = TRUE; } } else { if (PciAddress.ExtendedRegister != 0) { Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF; } else { Pci.Bits.Reg = PciAddress.Register; } // // Note: We can also use PciExpress access here, if wanted. // } if (!UsePciExpressAccess) { Pci.Bits.Func = PciAddress.Function; Pci.Bits.Dev = PciAddress.Device; Pci.Bits.Bus = PciAddress.Bus; Pci.Bits.Reserved = 0; Pci.Bits.Enable = 1; // // PCI Config access are all 32-bit alligned, but by accessing the // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types // are possible on PCI. // // To read a byte of PCI config space you load 0xcf8 and // read 0xcfc, 0xcfd, 0xcfe, 0xcff // PciDataStride = Pci.Bits.Reg & 0x03; while (Count) { PciAligned = Pci; PciAligned.Bits.Reg &= 0xfc; PciData = (UINTN)PrivateData->PciData + PciDataStride; EfiAcquireLock(&PrivateData->PciLock); This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned); if (Write) { This->Io.Write (This, Width, PciData, 1, UserBuffer); } else { This->Io.Read (This, Width, PciData, 1, UserBuffer); } EfiReleaseLock(&PrivateData->PciLock); UserBuffer = ((UINT8 *)UserBuffer) + OutStride; PciDataStride = (PciDataStride + InStride) % 4; Pci.Bits.Reg += InStride; Count -= 1; } } else { // // Access PCI-Express space by using memory mapped method. // PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) | (PciAddress.Bus << 20) | (PciAddress.Device << 15) | (PciAddress.Function << 12); if (PciAddress.ExtendedRegister != 0) { PciExpressRegAddr += PciAddress.ExtendedRegister; } else { PciExpressRegAddr += PciAddress.Register; } while (Count) { if (Write) { This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer); } else { This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer); } UserBuffer = ((UINT8 *) UserBuffer) + OutStride; PciExpressRegAddr += InStride; Count -= 1; } } return EFI_SUCCESS; }
EFI_STATUS libGetWakeupTime ( OUT BOOLEAN *Enabled, OUT BOOLEAN *Pending, OUT EFI_TIME *Time ) { EFI_STATUS Status; RTC_REGISTER_B RegisterB; RTC_REGISTER_C RegisterC; UINT8 Century; // // Check paramters for null pointers // if ((Enabled == NULL) || (Pending == NULL) || (Time == NULL)) { return EFI_INVALID_PARAMETER; } // // Acquire RTC Lock to make access to RTC atomic // EfiAcquireLock (&mRtc.RtcLock); // // Wait for up to 0.1 seconds for the RTC to be updated // Status = RtcWaitToUpdate (100000); if (EFI_ERROR (Status)) { EfiReleaseLock (&mRtc.RtcLock); return EFI_DEVICE_ERROR; } // // Read Register B and Register C // RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B); RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C); // // Get the Time/Date/Daylight Savings values. // *Enabled = RegisterB.Bits.AIE; if (*Enabled) { Time->Second = RtcRead (RTC_ADDRESS_SECONDS_ALARM); Time->Minute = RtcRead (RTC_ADDRESS_MINUTES_ALARM); Time->Hour = RtcRead (RTC_ADDRESS_HOURS_ALARM); Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH); Time->Month = RtcRead (RTC_ADDRESS_MONTH); Time->Year = RtcRead (RTC_ADDRESS_YEAR); } else { Time->Second = 0; Time->Minute = 0; Time->Hour = 0; Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH); Time->Month = RtcRead (RTC_ADDRESS_MONTH); Time->Year = RtcRead (RTC_ADDRESS_YEAR); } ConvertRtcTimeToEfiTime (Time, RegisterB); if (RtcTestCenturyRegister () == EFI_SUCCESS) { Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f)); } else { Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY)); } Time->Year = (UINT16) (Century * 100 + Time->Year); // // Release RTC Lock. // EfiReleaseLock (&mRtc.RtcLock); // // Make sure all field values are in correct range // Status = RtcTimeFieldsValid (Time); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } *Pending = RegisterC.Bits.AF; return EFI_SUCCESS; }