X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=EdkModulePkg%2FUniversal%2FPCD%2FDxe%2FService.c;h=97518510d6c63db29b53c4b5f753a2219c140c66;hp=280a45ea3188a88dc8c1d0b2a3f2a25c5c93a2e3;hb=4276d5dacfd4812abc1d7a1bd1da995d7002ee9e;hpb=878ddf1fc3540a715f63594ed22b6929e881afb4 diff --git a/EdkModulePkg/Universal/PCD/Dxe/Service.c b/EdkModulePkg/Universal/PCD/Dxe/Service.c index 280a45ea31..97518510d6 100644 --- a/EdkModulePkg/Universal/PCD/Dxe/Service.c +++ b/EdkModulePkg/Universal/PCD/Dxe/Service.c @@ -14,431 +14,656 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. Module Name: Service.c **/ -#include "../Common/PcdCommon.h" #include "Service.h" -static PCD_DATABASE *PrivatePcdDxeDatabase; -static LIST_ENTRY mPcdDatabaseListHead = INITIALIZE_LIST_HEAD_VARIABLE(mPcdDatabaseListHead); -LIST_ENTRY * -GetPcdDatabaseListHead ( - VOID - ) -{ - return &mPcdDatabaseListHead; -} +// +// Build Tool will generate DXE_PCD_DB_INIT_VALUE in Autogen.h +// Compression Algorithm will take care of the size optimization. +// -PCD_DATABASE * -GetPcdDxeDataBaseInstance ( - VOID -) -{ - return PrivatePcdDxeDatabase; -} - -PCD_DATABASE * -SetPcdDxeDataBaseInstance ( - PCD_DATABASE *PcdDatabase -) -{ - return PrivatePcdDxeDatabase = PcdDatabase; -} +PCD_DATABASE * mPcdDatabase; +LIST_ENTRY *mCallbackFnTable; -VOID -DxeGetPcdEntryWorker ( - IN UINTN TokenNumber, - IN CONST GUID *Guid, OPTIONAL - IN PCD_DATA_TYPE Type, - OUT VOID *Data +VOID * +GetWorker ( + UINTN TokenNumber, + UINTN GetSize ) { - PCD_DATABASE *Database; - Database = GetPcdDxeDataBaseInstance (); + UINT32 *LocalTokenNumberTable; + UINT16 *SizeTable; + BOOLEAN IsPeiDb; + UINTN Size; + UINT32 Offset; + EFI_GUID *GuidTable; + UINT16 *StringTable; + EFI_GUID *Guid; + UINT16 *Name; + VARIABLE_HEAD *VariableHead; + EFI_STATUS Status; + UINTN DataSize; + VOID *Data; + VPD_HEAD *VpdHead; + UINT8 *PcdDb; + UINT16 StringTableIdx; + UINT32 LocalTokenNumber; - GetPcdEntryWorker ( &Database->Info, - TokenNumber, - Guid, - Type, - Data - ); + // + // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER. + // We have to decrement TokenNumber by 1 to make it usable + // as the array index. + // + TokenNumber--; + + ASSERT (TokenNumber < PCD_TOTAL_TOKEN_NUMBER); + Size = DxePcdGetSize (TokenNumber + 1); + ASSERT (GetSize == Size || GetSize == 0); - return; -} + + IsPeiDb = (TokenNumber < PEI_LOCAL_TOKEN_NUMBER) ? TRUE : FALSE; + LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : + mPcdDatabase->DxeDb.Init.LocalTokenNumberTable; + SizeTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SizeTable: + mPcdDatabase->DxeDb.Init.SizeTable; -EFI_STATUS -DxeSetPcdEntryWorker ( - IN UINTN TokenNumber, - IN CONST GUID *Guid, OPTIONAL - IN PCD_DATA_TYPE Type, - IN CONST VOID *Data - ) -{ - PCD_DATABASE *Database; - PCD_INDEX *PcdIndex; - EFI_STATUS Status; + TokenNumber = IsPeiDb ? TokenNumber : + TokenNumber - PEI_LOCAL_TOKEN_NUMBER; - Database = GetPcdDxeDataBaseInstance (); + LocalTokenNumber = LocalTokenNumberTable[TokenNumber]; + + if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) { + LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size, IsPeiDb); + } + PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb); + StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable : + mPcdDatabase->DxeDb.Init.StringTable; + + Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK; + + switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) { + case PCD_TYPE_VPD: + VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset); + return (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset); + + case PCD_TYPE_HII: + GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable : + mPcdDatabase->DxeDb.Init.GuidTable; + + VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset); + + Guid = &(GuidTable[VariableHead->GuidTableIndex]); + Name = &(StringTable[VariableHead->StringIndex]); + + Status = GetHiiVariable (Guid, Name, &Data, &DataSize); + if (Status == EFI_SUCCESS) { + ASSERT (DataSize >= (UINTN) (VariableHead->Offset + Size)); + return (UINT8 *) Data + VariableHead->Offset; + } else { + // + // Return the default value specified by Platform Integrator + // + return (VOID *) ((UINT8 *) PcdDb + VariableHead->DefaultValueOffset); + } + + case PCD_TYPE_STRING: + StringTableIdx = (UINT16) *((UINT8 *) PcdDb + Offset); + return (VOID *) &StringTable[StringTableIdx]; + + case PCD_TYPE_DATA: + return (VOID *) ((UINT8 *) PcdDb + Offset); + break; + + default: + ASSERT (FALSE); + break; + + } - ASSERT (Data != NULL); + ASSERT (FALSE); + + return NULL; + +} - PcdIndex = FindPcdIndex (TokenNumber, Guid, &Database->Info, NULL); - ASSERT (PcdIndex != NULL); - ASSERT (PcdIndex->StateByte.DataType == Type); +EFI_STATUS +DxeRegisterCallBackWorker ( + IN UINTN TokenNumber, + IN CONST GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction +) +{ + CALLBACK_FN_ENTRY *FnTableEntry; + LIST_ENTRY *ListHead; + LIST_ENTRY *ListNode; + + if (Guid != NULL) { + TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber); + } // - // Invoke the callback function. + // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER. + // We have to decrement TokenNumber by 1 to make it usable + // as the array index. // + TokenNumber--; - Status = SetPcdData (PcdIndex, &Database->Info, Data); + ListHead = &mCallbackFnTable[TokenNumber]; + ListNode = GetFirstNode (ListHead); - return Status; + while (ListNode != ListHead) { + FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node); + + if (FnTableEntry->CallbackFn == CallBackFunction) { + // + // We only allow a Callback function to be register once + // for a TokenNumber. So just return EFI_SUCCESS + // + return EFI_SUCCESS; + } + ListNode = GetNextNode (ListHead, ListNode); + } + FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY)); + ASSERT (FnTableEntry != NULL); + FnTableEntry->CallbackFn = CallBackFunction; + InsertTailList (ListHead, &FnTableEntry->Node); + + return EFI_SUCCESS; } -UINTN -DxeGetPcdEntrySizeWorker ( - IN UINTN TokenNumber, - IN CONST GUID *Guid OPTIONAL - ) -{ - PCD_DATABASE *Database; - Database = GetPcdDxeDataBaseInstance (); - return GetPcdEntrySizeWorker (&Database->Info, - TokenNumber, - Guid - ); -} +EFI_STATUS +DxeUnRegisterCallBackWorker ( + IN UINTN TokenNumber, + IN CONST GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction +) +{ + CALLBACK_FN_ENTRY *FnTableEntry; + LIST_ENTRY *ListHead; + LIST_ENTRY *ListNode; + if (Guid != NULL) { + TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber); + } + // + // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER. + // We have to decrement TokenNumber by 1 to make it usable + // as the array index. + // + TokenNumber--; -LIST_ENTRY * -InsertToGuidSpaceListI ( - IN LIST_ENTRY *GuidSpaceListHead, - IN CONST EFI_GUID *Guid - ) -{ - PCD_GUID_SPACE *GuidSpaceEntry; + ListHead = &mCallbackFnTable[TokenNumber]; + ListNode = GetFirstNode (ListHead); - GuidSpaceEntry = AllocatePool (sizeof (PCD_GUID_SPACE)); - ASSERT (GuidSpaceEntry != NULL); + while (ListNode != ListHead) { + FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node); - GuidSpaceEntry->GuidSpace= Guid; - InitializeListHead (&GuidSpaceEntry->TokenSpaceHead); - - InsertTailList (GuidSpaceListHead, &GuidSpaceEntry->ListNode); + if (FnTableEntry->CallbackFn == CallBackFunction) { + // + // We only allow a Callback function to be register once + // for a TokenNumber. So we can safely remove the Node from + // the Link List and return EFI_SUCCESS. + // + RemoveEntryList (ListNode); + FreePool (FnTableEntry); + + return EFI_SUCCESS; + } + ListNode = GetNextNode (ListHead, ListNode); + } - return &GuidSpaceEntry->TokenSpaceHead; + return EFI_INVALID_PARAMETER; } -LIST_ENTRY * -InsertToTokenSpaceListI ( - IN LIST_ENTRY *TokenSpaceListHead, - IN UINTN TokenNumber +UINTN +ExGetNextTokeNumber ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN EFI_GUID *GuidTable, + IN UINTN SizeOfGuidTable, + IN DYNAMICEX_MAPPING *ExMapTable, + IN UINTN SizeOfExMapTable ) { - PCD_TOKEN_SPACE *TokenSpaceEntry; + EFI_GUID *MatchGuid; + UINTN Idx; + UINTN GuidTableIdx; + BOOLEAN Found; + + MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid); + if (MatchGuid == NULL) { + return PCD_INVALID_TOKEN_NUMBER; + } - TokenSpaceEntry = AllocatePool (sizeof (PCD_TOKEN_SPACE)); - ASSERT (TokenSpaceEntry != NULL); + Found = FALSE; + GuidTableIdx = MatchGuid - GuidTable; + for (Idx = 0; Idx < SizeOfExMapTable; Idx++) { + if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) { + Found = TRUE; + break; + } + } - TokenSpaceEntry->TokeNumber = TokenNumber; - InitializeListHead (&TokenSpaceEntry->CallbackListHead); - - InsertTailList (TokenSpaceListHead, &TokenSpaceEntry->ListNode); + if (Found) { + if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) { + return ExMapTable[Idx].ExTokenNumber; + } - return &TokenSpaceEntry->CallbackListHead; + for ( ; Idx < SizeOfExMapTable; Idx++) { + if (ExMapTable[Idx].ExTokenNumber == TokenNumber) { + Idx++; + if (Idx == SizeOfExMapTable) { + // + // Exceed the length of ExMap Table + // + return PCD_INVALID_TOKEN_NUMBER; + } else if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) { + // + // Found the next match + // + return ExMapTable[Idx].ExTokenNumber; + } else { + // + // Guid has been changed. It is the next Token Space Guid. + // We should flag no more TokenNumber. + // + return PCD_INVALID_TOKEN_NUMBER; + } + } + } + } + + return PCD_INVALID_TOKEN_NUMBER; } + VOID -InsertToCallbackListI ( - IN LIST_ENTRY *CallbackListHead, - IN PCD_PROTOCOL_CALLBACK CallBackFunction +BuildPcdDxeDataBase ( + VOID ) { - PCD_CALLBACK_ENTRY *CallbackEntry; - - CallbackEntry = AllocatePool (sizeof (PCD_CALLBACK_ENTRY)); - ASSERT (CallbackEntry != NULL); - CallbackEntry->CallbackFunction = CallBackFunction; - InsertTailList (CallbackListHead, &CallbackEntry->ListNode); + PEI_PCD_DATABASE *PeiDatabase; + EFI_HOB_GUID_TYPE *GuidHob; + UINTN Idx; + + mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE)); + ASSERT (mPcdDatabase != NULL); + + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); + + if (GuidHob != NULL) { + + // + // We will copy over the PEI phase's PCD Database. + // + // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM + // should not be included at all. So the GuidHob could + // be NULL. If it is NULL, we just copy over the DXE Default + // Value to PCD Database. + // + + PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob); + // + // Copy PCD Entries refereneced in PEI phase to PCD DATABASE + // + CopyMem (&mPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE)); + } + + // + // Copy PCD Entries with default value to PCD DATABASE + // + CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT)); + + + // + // Initialized the Callback Function Table + // + + if (PCD_TOTAL_TOKEN_NUMBER != 0) { + mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER * sizeof (LIST_ENTRY)); + } + for (Idx = 0; Idx < PCD_TOTAL_TOKEN_NUMBER; Idx++) { + InitializeListHead (&mCallbackFnTable[Idx]); + } + return; } - -VOID -InsertToCallbackList ( - IN UINTN TokenNumber, - IN CONST EFI_GUID *Guid, - IN PCD_PROTOCOL_CALLBACK CallBackFunction +EFI_STATUS +GetHiiVariable ( + IN EFI_GUID *VariableGuid, + IN UINT16 *VariableName, + OUT VOID ** VariableData, + OUT UINTN *VariableSize ) { - LIST_ENTRY *GuidListNode; - LIST_ENTRY *GuidListHead; - LIST_ENTRY *TokenListNode; - LIST_ENTRY *TokenListHead; - LIST_ENTRY *CallbackListHead; - PCD_GUID_SPACE *GuidSpaceEntry; - PCD_TOKEN_SPACE *TokenSpaceEntry; + UINTN Size; + EFI_STATUS Status; + VOID *Buffer; + Size = 0; + Buffer = NULL; - GuidListHead = GetPcdDatabaseListHead (); - - GuidListNode = GetFirstNode (GuidListHead); - while (!IsNull (GuidListNode, GuidListHead)) { - GuidSpaceEntry = PCD_GUID_SPACE_FROM_LISTNODE(GuidListNode); - - if (CompareGuid (GuidSpaceEntry->GuidSpace, Guid)) { - TokenListHead = &GuidSpaceEntry->TokenSpaceHead; - TokenListNode = GetFirstNode (TokenListHead); - while (!IsNull (TokenListNode, TokenListHead)) { - TokenSpaceEntry = PCD_TOKEN_SPACE_FROM_LISTNODE(TokenListNode); - if (TokenSpaceEntry->TokeNumber == TokenNumber) { - InsertToCallbackListI (&TokenSpaceEntry->CallbackListHead , CallBackFunction); - } - } + Status = EfiGetVariable ( + (UINT16 *)VariableName, + VariableGuid, + NULL, + &Size, + Buffer + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { - // - // No TokenNumber match input found in this GuidSpace - // - CallbackListHead = InsertToTokenSpaceListI (TokenListHead, TokenNumber); - InsertToCallbackListI (CallbackListHead , CallBackFunction); - } - - GuidListNode = GetNextNode (GuidListHead, GuidListNode); + Buffer = AllocatePool (Size); + + ASSERT (Buffer != NULL); + + Status = EfiGetVariable ( + VariableName, + VariableGuid, + NULL, + &Size, + Buffer + ); + + ASSERT (Status == EFI_SUCCESS); } - // - // No GuidSpace match the input Guid, so build the GuidSpace, TokenNumberSpace and Callback - // - TokenListHead = InsertToGuidSpaceListI (GuidListHead, Guid); - CallbackListHead = InsertToTokenSpaceListI (TokenListHead, TokenNumber); - InsertToCallbackListI (CallbackListHead , CallBackFunction); + *VariableData = Buffer; + *VariableSize = Size; + + return Status; - return; - } -EFI_STATUS -RemoveFromCallbackListI ( - IN LIST_ENTRY *CallbackListHead, - IN PCD_PROTOCOL_CALLBACK CallBackFunction - ) + +UINT32 +GetSkuEnabledTokenNumber ( + UINT32 LocalTokenNumber, + UINTN Size, + BOOLEAN IsPeiDb + ) { - LIST_ENTRY *ListNode; - PCD_CALLBACK_ENTRY *CallbackEntry; + SKU_HEAD *SkuHead; + SKU_ID *SkuIdTable; + INTN i; + UINT8 *Value; + SKU_ID *PhaseSkuIdTable; + UINT8 *PcdDb; - ListNode = GetFirstNode (CallbackListHead); + ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0); - while (!IsNull(CallbackListHead, ListNode)) { - CallbackEntry = PCD_CALLBACK_ENTRY_FROM_LISTNODE(ListNode); + PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb; - if (CallbackEntry->CallbackFunction == CallBackFunction) { - RemoveEntryList (ListNode); - FreePool (CallbackEntry); - return EFI_SUCCESS; + SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK)); + Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset); + + PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable : + mPcdDatabase->DxeDb.Init.SkuIdTable; + + SkuIdTable = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset]; + + for (i = 0; i < SkuIdTable[0]; i++) { + if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[i + 1]) { + break; } - ListNode = GetNextNode (CallbackListHead, ListNode); } + ASSERT (i < SkuIdTable[0]); - return EFI_NOT_FOUND; + switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) { + case PCD_TYPE_VPD: + Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]); + return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD); + + case PCD_TYPE_HII: + Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]); + return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII); + + case PCD_TYPE_DATA: + Value += Size * i; + return (UINT32) (Value - PcdDb); + + default: + ASSERT (FALSE); + } + + ASSERT (FALSE); + + return 0; + } -EFI_STATUS -RemoveFromCallbackList ( - IN UINTN TokenNumber, - IN CONST GUID *Guid, - IN PCD_PROTOCOL_CALLBACK CallBackFunction + + +VOID +InvokeCallbackOnSet ( + UINT32 ExTokenNumber, + CONST EFI_GUID *Guid, OPTIONAL + UINTN TokenNumber, + VOID *Data, + UINTN Size ) { - LIST_ENTRY *GuidListNode; - LIST_ENTRY *GuidListHead; - LIST_ENTRY *TokenListNode; - LIST_ENTRY *TokenListHead; - PCD_GUID_SPACE *GuidSpaceEntry; - PCD_TOKEN_SPACE *TokenSpaceEntry; + CALLBACK_FN_ENTRY *FnTableEntry; + LIST_ENTRY *ListHead; + LIST_ENTRY *ListNode; + // + // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER. + // We have to decrement TokenNumber by 1 to make it usable + // as the array index. + // + TokenNumber--; - GuidListHead = GetPcdDatabaseListHead (); + ListHead = &mCallbackFnTable[TokenNumber]; + ListNode = GetFirstNode (ListHead); - GuidListNode = GetFirstNode (GuidListHead); - while (!IsNull (GuidListNode, GuidListHead)) { - - GuidSpaceEntry = PCD_GUID_SPACE_FROM_LISTNODE(GuidListNode); - if (CompareGuid (GuidSpaceEntry->GuidSpace, Guid)) { - - TokenListHead = &GuidSpaceEntry->TokenSpaceHead; - TokenListNode = GetFirstNode (TokenListHead); - while (!IsNull (TokenListNode, TokenListHead)) { - - TokenSpaceEntry = PCD_TOKEN_SPACE_FROM_LISTNODE(TokenListNode); - if (TokenSpaceEntry->TokeNumber == TokenNumber) { - return RemoveFromCallbackListI (&TokenSpaceEntry->CallbackListHead , CallBackFunction); - } - } + while (ListNode != ListHead) { + FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node); - // - // No TokenNumber match input found in this GuidSpace - // - return EFI_NOT_FOUND; - } + FnTableEntry->CallbackFn(Guid, + (Guid == NULL) ? TokenNumber : ExTokenNumber, + Data, + Size); - GuidListNode = GetNextNode (GuidListHead, GuidListNode); + ListNode = GetNextNode (ListHead, ListNode); } - - - return EFI_NOT_FOUND; + return; } + EFI_STATUS -DxeRegisterCallBackWorker ( - IN UINTN TokenNumber, - IN CONST GUID *Guid, OPTIONAL - IN PCD_PROTOCOL_CALLBACK CallBackFunction, - IN BOOLEAN Register -) +SetWorker ( + UINTN TokenNumber, + VOID *Data, + UINTN Size, + BOOLEAN PtrType + ) { - PCD_DATABASE *Database; - PCD_INDEX *PcdIndex; - - Database = GetPcdDxeDataBaseInstance (); - - PcdIndex = FindPcdIndex (TokenNumber, Guid, &Database->Info, NULL); + UINT32 *LocalTokenNumberTable; + BOOLEAN IsPeiDb; + UINT32 LocalTokenNumber; + EFI_GUID *GuidTable; + UINT16 *StringTable; + EFI_GUID *Guid; + UINT16 *Name; + UINTN VariableOffset; + VOID *InternalData; + VARIABLE_HEAD *VariableHead; + UINTN Offset; + UINT8 *PcdDb; - if (PcdIndex == NULL) { - return EFI_NOT_FOUND; - } + // + // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER. + // We have to decrement TokenNumber by 1 to make it usable + // as the array index. + // + TokenNumber--; + + ASSERT (TokenNumber < PCD_TOTAL_TOKEN_NUMBER); - if (Register) { - InsertToCallbackList (TokenNumber, Guid, CallBackFunction); - return EFI_SUCCESS; + if (PtrType) { + ASSERT (Size <= DxePcdGetSize (TokenNumber + 1)); } else { - return RemoveFromCallbackList (TokenNumber, Guid, CallBackFunction); + ASSERT (Size == DxePcdGetSize (TokenNumber + 1)); } + + IsPeiDb = (TokenNumber < PEI_LOCAL_TOKEN_NUMBER) ? TRUE : FALSE; - } + LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : + mPcdDatabase->DxeDb.Init.LocalTokenNumberTable; + if ((TokenNumber < PEI_NEX_TOKEN_NUMBER) || + (TokenNumber >= PEI_LOCAL_TOKEN_NUMBER || TokenNumber < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER))) { + InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, Size); + } + TokenNumber = IsPeiDb ? TokenNumber + : TokenNumber - PEI_LOCAL_TOKEN_NUMBER; -EFI_STATUS -DxeSetSku ( - UINTN Id -) -{ - PCD_DATABASE * Database; + LocalTokenNumber = LocalTokenNumberTable[TokenNumber]; + + if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) { + LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size, IsPeiDb); + } - Database = GetPcdDxeDataBaseInstance (); + Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK; - return Database->Info.SkuId = Id; + PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb); -} + StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable : + mPcdDatabase->DxeDb.Init.StringTable; + + InternalData = PcdDb + Offset; + switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) { + case PCD_TYPE_VPD: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + + case PCD_TYPE_STRING: + CopyMem (&StringTable[*((UINT16 *)InternalData)], Data, Size); + return EFI_SUCCESS; + case PCD_TYPE_HII: + // + // Bug Bug: Please implement this + // + GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable : + mPcdDatabase->DxeDb.Init.GuidTable; + + VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset); + + Guid = &(GuidTable[VariableHead->GuidTableIndex]); + Name = &(StringTable[VariableHead->StringIndex]); + VariableOffset = VariableHead->Offset; -EFI_STATUS -DxeGetNextTokenWorker ( - IN OUT UINTN *TokenNumber, - IN CONST GUID *Guid OPTIONAL - ) -{ - PCD_DATABASE * Database; + return SetHiiVariable (Guid, Name, Data, Size, VariableOffset); - Database = GetPcdDxeDataBaseInstance (); + case PCD_TYPE_DATA: + if (PtrType) { + CopyMem (InternalData, Data, Size); + return EFI_SUCCESS; + } - return GetNextTokenWorker (&Database->Info, - TokenNumber, - Guid - ); -} + switch (Size) { + case sizeof(UINT8): + *((UINT8 *) InternalData) = *((UINT8 *) Data); + return EFI_SUCCESS; + case sizeof(UINT16): + *((UINT16 *) InternalData) = *((UINT16 *) Data); + return EFI_SUCCESS; + case sizeof(UINT32): + *((UINT32 *) InternalData) = *((UINT32 *) Data); + return EFI_SUCCESS; -VOID -InitPcdDxeDataBase ( - VOID -) -{ - PCD_DATABASE *PeiDatabase; - PCD_DATABASE *DxeDatabase; - EFI_HOB_GUID_TYPE *GuidHob; + case sizeof(UINT64): + *((UINT64 *) InternalData) = *((UINT64 *) Data); + return EFI_SUCCESS; - GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); - ASSERT (GuidHob != NULL); + default: + ASSERT (FALSE); + return EFI_NOT_FOUND; + } - PeiDatabase = (PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob); + default: + ASSERT (FALSE); + break; + } + + ASSERT (FALSE); + return EFI_NOT_FOUND; +} - DxeDatabase = AllocateCopyPool (PeiDatabase->Info.DatabaseLen, PeiDatabase); - ASSERT (DxeDatabase != NULL); - SetPcdDxeDataBaseInstance (DxeDatabase); - return; + +VOID * +ExGetWorker ( + IN CONST EFI_GUID *Guid, + IN UINTN ExTokenNumber, + IN UINTN GetSize + ) +{ + return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize); } + + EFI_STATUS -GetHiiVariable ( - IN EFI_GUID *VariableGuid, - IN UINT16 *VariableName, - OUT VOID ** VariableData, - OUT UINTN *VariableSize +ExSetWorker ( + IN UINTN ExTokenNumber, + IN CONST EFI_GUID *Guid, + VOID *Data, + UINTN SetSize, + BOOLEAN PtrType ) { - UINTN Size; - EFI_STATUS Status; - VOID *Buffer; - - Status = EfiGetVariable ( - (UINT16 *)VariableName, - VariableGuid, - NULL, - &Size, - NULL - ); - ASSERT (Status == EFI_BUFFER_TOO_SMALL); - - Buffer = AllocatePool (Size); - - ASSERT (Buffer != NULL); + UINTN TokenNumber; + + TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber); - Status = EfiGetVariable ( - VariableName, - VariableGuid, - NULL, - &Size, - Buffer - ); + InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, SetSize); - return Status; + SetWorker (TokenNumber, Data, SetSize, PtrType); + return EFI_SUCCESS; + } + EFI_STATUS SetHiiVariable ( IN EFI_GUID *VariableGuid, @@ -448,44 +673,108 @@ SetHiiVariable ( IN UINTN Offset ) { - UINTN Size; - VOID *Buffer; - EFI_STATUS Status; + UINTN Size; + VOID *Buffer; + EFI_STATUS Status; + UINT32 Attribute; Size = 0; Status = EfiGetVariable ( (UINT16 *)VariableName, VariableGuid, - NULL, + &Attribute, &Size, NULL ); - ASSERT (Status == EFI_BUFFER_TOO_SMALL); + if (Status == EFI_BUFFER_TOO_SMALL) { - Buffer = AllocatePool (Size); + Buffer = AllocatePool (Size); - ASSERT (Buffer != NULL); + ASSERT (Buffer != NULL); - Status = EfiGetVariable ( - VariableName, - VariableGuid, - NULL, - &Size, - Buffer - ); + Status = EfiGetVariable ( + VariableName, + VariableGuid, + &Attribute, + &Size, + Buffer + ); + + ASSERT_EFI_ERROR (Status); + CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize); + + } else { - CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize); + Attribute = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; + Size = DataSize + Offset; + Buffer = AllocateZeroPool (Size); + ASSERT (Buffer != NULL); + CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize); + + } return EfiSetVariable ( - VariableName, - VariableGuid, - 0, - Size, - Buffer - ); + VariableName, + VariableGuid, + Attribute, + Size, + Buffer + ); + +} + + + + + +UINTN +GetExPcdTokenNumber ( + IN CONST EFI_GUID *Guid, + IN UINT32 ExTokenNumber + ) +{ + UINT32 i; + DYNAMICEX_MAPPING *ExMap; + EFI_GUID *GuidTable; + EFI_GUID *MatchGuid; + UINTN MatchGuidIdx; + + ExMap = mPcdDatabase->PeiDb.Init.ExMapTable; + GuidTable = mPcdDatabase->PeiDb.Init.GuidTable; + + MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid); + ASSERT (MatchGuid != NULL); + + MatchGuidIdx = MatchGuid - GuidTable; + + for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) { + if ((ExTokenNumber == ExMap[i].ExTokenNumber) && + (MatchGuidIdx == ExMap[i].ExGuidIndex)) { + return ExMap[i].LocalTokenNumber; + + } + } + + ExMap = mPcdDatabase->DxeDb.Init.ExMapTable; + GuidTable = mPcdDatabase->DxeDb.Init.GuidTable; + + MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid); + ASSERT (MatchGuid != NULL); + + MatchGuidIdx = MatchGuid - GuidTable; + + for (i = 0; i < DXE_EXMAPPING_TABLE_SIZE; i++) { + if ((ExTokenNumber == ExMap[i].ExTokenNumber) && + (MatchGuidIdx == ExMap[i].ExGuidIndex)) { + return ExMap[i].LocalTokenNumber + PEI_LOCAL_TOKEN_NUMBER; + } + } + + ASSERT (FALSE); + return 0; }