| /*++ | |
| Copyright (c) 2006, Intel Corporation | |
| All rights reserved. This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| Module Name: | |
| Library.c | |
| Abstract: | |
| DXE Core library services. | |
| --*/ | |
| #include <DxeMain.h> | |
| UINTN mErrorLevel = EFI_D_ERROR | EFI_D_LOAD; | |
| EFI_DEVICE_HANDLE_EXTENDED_DATA mStatusCodeData = { | |
| { | |
| sizeof (EFI_STATUS_CODE_DATA), | |
| 0, | |
| EFI_STATUS_CODE_SPECIFIC_DATA_GUID | |
| }, | |
| NULL | |
| }; | |
| VOID | |
| CoreReportProgressCodeSpecific ( | |
| IN EFI_STATUS_CODE_VALUE Value, | |
| IN EFI_HANDLE Handle | |
| ) | |
| /*++ | |
| Routine Description: | |
| Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid, | |
| with a handle as additional information. | |
| Arguments: | |
| Value - Describes the class/subclass/operation of the hardware or software entity | |
| that the Status Code relates to. | |
| Handle - Additional information. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| mStatusCodeData.DataHeader.Size = sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - sizeof (EFI_STATUS_CODE_DATA); | |
| mStatusCodeData.Handle = Handle; | |
| if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) { | |
| gStatusCode->ReportStatusCode ( | |
| EFI_PROGRESS_CODE, | |
| Value, | |
| 0, | |
| &gEfiDxeServicesTableGuid, | |
| (EFI_STATUS_CODE_DATA *) &mStatusCodeData | |
| ); | |
| } | |
| } | |
| VOID | |
| CoreReportProgressCode ( | |
| IN EFI_STATUS_CODE_VALUE Value | |
| ) | |
| /*++ | |
| Routine Description: | |
| Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid. | |
| Arguments: | |
| Value - Describes the class/subclass/operation of the hardware or software entity | |
| that the Status Code relates to. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) { | |
| gStatusCode->ReportStatusCode ( | |
| EFI_PROGRESS_CODE, | |
| Value, | |
| 0, | |
| &gEfiDxeServicesTableGuid, | |
| NULL | |
| ); | |
| } | |
| } | |
| VOID * | |
| CoreAllocateBootServicesPool ( | |
| IN UINTN AllocationSize | |
| ) | |
| /*++ | |
| Routine Description: | |
| Allocate pool of type EfiBootServicesData, the size is specified with AllocationSize. | |
| Arguments: | |
| AllocationSize - Size to allocate. | |
| Returns: | |
| Pointer of the allocated pool. | |
| --*/ | |
| { | |
| VOID *Memory; | |
| CoreAllocatePool (EfiBootServicesData, AllocationSize, &Memory); | |
| return Memory; | |
| } | |
| VOID * | |
| CoreAllocateZeroBootServicesPool ( | |
| IN UINTN AllocationSize | |
| ) | |
| /*++ | |
| Routine Description: | |
| Allocate pool of type EfiBootServicesData and zero it, the size is specified with AllocationSize. | |
| Arguments: | |
| AllocationSize - Size to allocate. | |
| Returns: | |
| Pointer of the allocated pool. | |
| --*/ | |
| { | |
| VOID *Memory; | |
| Memory = CoreAllocateBootServicesPool (AllocationSize); | |
| SetMem (Memory, (Memory == NULL) ? 0 : AllocationSize, 0); | |
| return Memory; | |
| } | |
| VOID * | |
| CoreAllocateCopyPool ( | |
| IN UINTN AllocationSize, | |
| IN VOID *Buffer | |
| ) | |
| /*++ | |
| Routine Description: | |
| Allocate pool of specified size with EfiBootServicesData type, and copy specified buffer to this pool. | |
| Arguments: | |
| AllocationSize - Size to allocate. | |
| Buffer - Specified buffer that will be copy to the allocated pool | |
| Returns: | |
| Pointer of the allocated pool. | |
| --*/ | |
| { | |
| VOID *Memory; | |
| Memory = CoreAllocateBootServicesPool (AllocationSize); | |
| CopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize); | |
| return Memory; | |
| } | |
| VOID * | |
| CoreAllocateRuntimePool ( | |
| IN UINTN AllocationSize | |
| ) | |
| /*++ | |
| Routine Description: | |
| Allocate pool of type EfiRuntimeServicesData, the size is specified with AllocationSize. | |
| Arguments: | |
| AllocationSize - Size to allocate. | |
| Returns: | |
| Pointer of the allocated pool. | |
| --*/ | |
| { | |
| VOID *Memory; | |
| CoreAllocatePool (EfiRuntimeServicesData, AllocationSize, &Memory); | |
| return Memory; | |
| } | |
| VOID * | |
| CoreAllocateRuntimeCopyPool ( | |
| IN UINTN AllocationSize, | |
| IN VOID *Buffer | |
| ) | |
| /*++ | |
| Routine Description: | |
| Allocate pool of specified size with EfiRuntimeServicesData type, and copy specified buffer to this pool. | |
| Arguments: | |
| AllocationSize - Size to allocate. | |
| Buffer - Specified buffer that will be copy to the allocated pool | |
| Returns: | |
| Pointer of the allocated pool. | |
| --*/ | |
| { | |
| VOID *Memory; | |
| Memory = CoreAllocateRuntimePool (AllocationSize); | |
| CopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize); | |
| return Memory; | |
| } | |
| // | |
| // Lock Stuff | |
| // | |
| EFI_STATUS | |
| CoreAcquireLockOrFail ( | |
| IN EFI_LOCK *Lock | |
| ) | |
| /*++ | |
| Routine Description: | |
| Initialize a basic mutual exclusion lock. Each lock | |
| provides mutual exclusion access at it's task priority | |
| level. Since there is no-premption (at any TPL) or | |
| multiprocessor support, acquiring the lock only consists | |
| of raising to the locks TPL. | |
| Arguments: | |
| Lock - The EFI_LOCK structure to initialize | |
| Returns: | |
| EFI_SUCCESS - Lock Owned. | |
| EFI_ACCESS_DENIED - Reentrant Lock Acquisition, Lock not Owned. | |
| --*/ | |
| { | |
| ASSERT (Lock != NULL); | |
| ASSERT (Lock->Lock != EfiLockUninitialized); | |
| if (Lock->Lock == EfiLockAcquired) { | |
| // | |
| // Lock is already owned, so bail out | |
| // | |
| return EFI_ACCESS_DENIED; | |
| } | |
| Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl); | |
| Lock->Lock = EfiLockAcquired; | |
| return EFI_SUCCESS; | |
| } | |
| VOID | |
| CoreAcquireLock ( | |
| IN EFI_LOCK *Lock | |
| ) | |
| /*++ | |
| Routine Description: | |
| Raising to the task priority level of the mutual exclusion | |
| lock, and then acquires ownership of the lock. | |
| Arguments: | |
| Lock - The lock to acquire | |
| Returns: | |
| Lock owned | |
| --*/ | |
| { | |
| ASSERT (Lock != NULL); | |
| ASSERT (Lock->Lock == EfiLockReleased); | |
| Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl); | |
| Lock->Lock = EfiLockAcquired; | |
| } | |
| VOID | |
| CoreReleaseLock ( | |
| IN EFI_LOCK *Lock | |
| ) | |
| /*++ | |
| Routine Description: | |
| Releases ownership of the mutual exclusion lock, and | |
| restores the previous task priority level. | |
| Arguments: | |
| Lock - The lock to release | |
| Returns: | |
| Lock unowned | |
| --*/ | |
| { | |
| EFI_TPL Tpl; | |
| ASSERT (Lock != NULL); | |
| ASSERT (Lock->Lock == EfiLockAcquired); | |
| Tpl = Lock->OwnerTpl; | |
| Lock->Lock = EfiLockReleased; | |
| CoreRestoreTpl (Tpl); | |
| } | |
| UINTN | |
| CoreDevicePathSize ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| /*++ | |
| Routine Description: | |
| Calculate the size of a whole device path. | |
| Arguments: | |
| DevicePath - The pointer to the device path data. | |
| Returns: | |
| Size of device path data structure.. | |
| --*/ | |
| { | |
| EFI_DEVICE_PATH_PROTOCOL *Start; | |
| if (DevicePath == NULL) { | |
| return 0; | |
| } | |
| // | |
| // Search for the end of the device path structure | |
| // | |
| Start = DevicePath; | |
| while (!EfiIsDevicePathEnd (DevicePath)) { | |
| DevicePath = EfiNextDevicePathNode (DevicePath); | |
| } | |
| // | |
| // Compute the size and add back in the size of the end device path structure | |
| // | |
| return ((UINTN)DevicePath - (UINTN)Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL); | |
| } | |
| BOOLEAN | |
| CoreIsDevicePathMultiInstance ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| /*++ | |
| Routine Description: | |
| Return TRUE is this is a multi instance device path. | |
| Arguments: | |
| DevicePath - A pointer to a device path data structure. | |
| Returns: | |
| TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi | |
| instance. | |
| --*/ | |
| { | |
| EFI_DEVICE_PATH_PROTOCOL *Node; | |
| if (DevicePath == NULL) { | |
| return FALSE; | |
| } | |
| Node = DevicePath; | |
| while (!EfiIsDevicePathEnd (Node)) { | |
| if (EfiIsDevicePathEndInstance (Node)) { | |
| return TRUE; | |
| } | |
| Node = EfiNextDevicePathNode (Node); | |
| } | |
| return FALSE; | |
| } | |
| EFI_DEVICE_PATH_PROTOCOL * | |
| CoreDuplicateDevicePath ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| /*++ | |
| Routine Description: | |
| Duplicate a new device path data structure from the old one. | |
| Arguments: | |
| DevicePath - A pointer to a device path data structure. | |
| Returns: | |
| A pointer to the new allocated device path data. | |
| Caller must free the memory used by DevicePath if it is no longer needed. | |
| --*/ | |
| { | |
| EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; | |
| UINTN Size; | |
| if (DevicePath == NULL) { | |
| return NULL; | |
| } | |
| // | |
| // Compute the size | |
| // | |
| Size = CoreDevicePathSize (DevicePath); | |
| // | |
| // Allocate space for duplicate device path | |
| // | |
| NewDevicePath = CoreAllocateCopyPool (Size, DevicePath); | |
| return NewDevicePath; | |
| } | |
| EFI_DEVICE_PATH_PROTOCOL * | |
| CoreAppendDevicePath ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *Src1, | |
| IN EFI_DEVICE_PATH_PROTOCOL *Src2 | |
| ) | |
| /*++ | |
| Routine Description: | |
| Function is used to append a Src1 and Src2 together. | |
| Arguments: | |
| Src1 - A pointer to a device path data structure. | |
| Src2 - A pointer to a device path data structure. | |
| Returns: | |
| A pointer to the new device path is returned. | |
| NULL is returned if space for the new device path could not be allocated from pool. | |
| It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed. | |
| --*/ | |
| { | |
| UINTN Size; | |
| UINTN Size1; | |
| UINTN Size2; | |
| EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; | |
| EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath; | |
| if (Src1 == NULL && Src2 == NULL) { | |
| return NULL; | |
| } | |
| // | |
| // Allocate space for the combined device path. It only has one end node of | |
| // length EFI_DEVICE_PATH_PROTOCOL | |
| // | |
| Size1 = CoreDevicePathSize (Src1); | |
| Size2 = CoreDevicePathSize (Src2); | |
| Size = Size1 + Size2 - sizeof(EFI_DEVICE_PATH_PROTOCOL); | |
| NewDevicePath = CoreAllocateCopyPool (Size, Src1); | |
| if (NewDevicePath != NULL) { | |
| // | |
| // Over write Src1 EndNode and do the copy | |
| // | |
| SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)((CHAR8 *)NewDevicePath + (Size1 - sizeof(EFI_DEVICE_PATH_PROTOCOL))); | |
| CopyMem (SecondDevicePath, Src2, Size2); | |
| } | |
| return NewDevicePath; | |
| } | |
| EFI_EVENT | |
| CoreCreateProtocolNotifyEvent ( | |
| IN EFI_GUID *ProtocolGuid, | |
| IN EFI_TPL NotifyTpl, | |
| IN EFI_EVENT_NOTIFY NotifyFunction, | |
| IN VOID *NotifyContext, | |
| OUT VOID **Registration, | |
| IN BOOLEAN SignalFlag | |
| ) | |
| /*++ | |
| Routine Description: | |
| Create a protocol notification event and return it. | |
| Arguments: | |
| ProtocolGuid - Protocol to register notification event on. | |
| NotifyTpl - Maximum TPL to signal the NotifyFunction. | |
| NotifyFuncition - EFI notification routine. | |
| NotifyContext - Context passed into Event when it is created. | |
| Registration - Registration key returned from RegisterProtocolNotify(). | |
| SignalFlag - Boolean value to decide whether kick the event after register or not. | |
| Returns: | |
| The EFI_EVENT that has been registered to be signaled when a ProtocolGuid | |
| is added to the system. | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| EFI_EVENT Event; | |
| // | |
| // Create the event | |
| // | |
| Status = CoreCreateEvent ( | |
| EVT_NOTIFY_SIGNAL, | |
| NotifyTpl, | |
| NotifyFunction, | |
| NotifyContext, | |
| &Event | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| // | |
| // Register for protocol notifactions on this event | |
| // | |
| Status = CoreRegisterProtocolNotify ( | |
| ProtocolGuid, | |
| Event, | |
| Registration | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| if (SignalFlag) { | |
| // | |
| // Kick the event so we will perform an initial pass of | |
| // current installed drivers | |
| // | |
| CoreSignalEvent (Event); | |
| } | |
| return Event; | |
| } | |