/** 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; }
/** 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; }
/** Acquires lock only at boot time. Simply returns at runtime. This is a temperary function that will be removed when EfiAcquireLock() in UefiLib can handle the call in UEFI Runtimer driver in RT phase. It calls EfiAcquireLock() at boot time, and simply returns at runtime. @param Lock A pointer to the lock to acquire. **/ VOID AcquireLockOnlyAtBootTime ( IN EFI_LOCK *Lock ) { if (!EfiAtRuntime ()) { EfiAcquireLock (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 NtfsAcquireLock ( VOID ) /*++ Routine Description: Lock the volume. Arguments: None. Returns: None. --*/ { EfiAcquireLock (&NtfsFsLock); }
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; }
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; }
/** 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; }
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 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; }
/** 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; }
// // ////////////////////////////////////////////////////////// // // 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; }
// // 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; }
// // ////////////////////////////////////////////////////////// // // 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; }
/** 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; }
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 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; }
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; }