X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=EdkModulePkg%2FUniversal%2FPCD%2FDxe%2FService.c;h=13abab001a824920ad34cfc345169dd56f50b335;hp=52097ade7e877d0baef83fd08a6c4362db1becee;hb=a696a78c371709fc6a74295296c92c4e94b23a1d;hpb=52e1905d39d71e013d253845cf8f2cdabea7c4f9 diff --git a/EdkModulePkg/Universal/PCD/Dxe/Service.c b/EdkModulePkg/Universal/PCD/Dxe/Service.c index 52097ade7e..13abab001a 100644 --- a/EdkModulePkg/Universal/PCD/Dxe/Service.c +++ b/EdkModulePkg/Universal/PCD/Dxe/Service.c @@ -1,5 +1,5 @@ /** @file -Private functions used by PCD DXE driver.s +Private functions used by PCD DXE driver. Copyright (c) 2006, Intel Corporation All rights reserved. This program and the accompanying materials @@ -17,75 +17,141 @@ Module Name: Service.c #include "Service.h" -// -// Build Tool will generate DXE_PCD_DB_INIT_VALUE in Autogen.h -// Compression Algorithm will take care of the size optimization. -// +PCD_DATABASE * mPcdDatabase; -/* -DXE_PCD_DATABASE_INIT gDXEPcdDbInit = { - DXE_PCD_DB_INIT_VALUE -}; -*/ - -PCD_DATABASE * gPcdDatabase; +LIST_ENTRY *mCallbackFnTable; VOID * -GetWorkerByLocalTokenNumber ( - UINT32 LocalTokenNumber, - BOOLEAN IsPeiDb, - UINTN Size - ) +GetWorker ( + UINTN TokenNumber, + UINTN GetSize + ) { - UINT32 Offset; + UINT32 *LocalTokenNumberTable; + UINT16 *SizeTable; EFI_GUID *GuidTable; UINT16 *StringTable; EFI_GUID *Guid; UINT16 *Name; VARIABLE_HEAD *VariableHead; - EFI_STATUS Status; - UINTN DataSize; - VOID *Data; + UINT8 *VaraiableDefaultBuffer; + UINT8 *Data; VPD_HEAD *VpdHead; UINT8 *PcdDb; + VOID *RetPtr; + UINTN MaxSize; + UINTN TmpTokenNumber; + UINTN DataSize; + EFI_STATUS Status; + UINT32 LocalTokenNumber; + UINT32 Offset; UINT16 StringTableIdx; + BOOLEAN IsPeiDb; + + // + // Aquire lock to prevent reentrance from TPL_CALLBACK level + // + EfiAcquireLock (&mPcdDatabaseLock); + + RetPtr = NULL; + // + // 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--; + + TmpTokenNumber = TokenNumber; + + // + // PCD_TOTAL_TOKEN_NUMBER is a auto-generated constant. + // It could be zero. EBC compiler is very choosy. It may + // report warning. So we add 1 in each size of the + // comparison. + // + ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1); + + ASSERT ((GetSize == DxePcdGetSize (TokenNumber + 1)) || (GetSize == 0)); + // EBC compiler is very choosy. It may report warning about comparison + // between UINTN and 0 . So we add 1 in each size of the + // comparison. + IsPeiDb = (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE; + + LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : + mPcdDatabase->DxeDb.Init.LocalTokenNumberTable; + + SizeTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SizeTable: + mPcdDatabase->DxeDb.Init.SizeTable; + + TokenNumber = IsPeiDb ? TokenNumber : + TokenNumber - PEI_LOCAL_TOKEN_NUMBER; + + LocalTokenNumber = LocalTokenNumberTable[TokenNumber]; + if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) { - LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size, IsPeiDb); + if (GetSize == 0) { + GetPtrTypeSize (TmpTokenNumber, &MaxSize); + } else { + MaxSize = GetSize; + } + LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb); } - PcdDb = IsPeiDb ? ((UINT8 *) &gPcdDatabase->PeiDb) : ((UINT8 *) &gPcdDatabase->DxeDb); - StringTable = IsPeiDb ? gPcdDatabase->PeiDb.Init.StringTable : - gPcdDatabase->DxeDb.Init.StringTable; + 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) { + switch (LocalTokenNumber & PCD_TYPE_ALL_SET) { case PCD_TYPE_VPD: VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset); - return (VOID *) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset); + RetPtr = (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset); + break; case PCD_TYPE_HII: - GuidTable = IsPeiDb ? gPcdDatabase->PeiDb.Init.GuidTable : - gPcdDatabase->DxeDb.Init.GuidTable; + GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable : + mPcdDatabase->DxeDb.Init.GuidTable; VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset); Guid = &(GuidTable[VariableHead->GuidTableIndex]); Name = &(StringTable[VariableHead->StringIndex]); + VaraiableDefaultBuffer = (UINT8 *) PcdDb + VariableHead->DefaultValueOffset; Status = GetHiiVariable (Guid, Name, &Data, &DataSize); - ASSERT_EFI_ERROR (Status); - ASSERT (DataSize >= (UINTN) (VariableHead->Offset + Size)); - - return (UINT8 *) Data + VariableHead->Offset; + if (Status == EFI_SUCCESS) { + if (GetSize == 0) { + // + // It is a pointer type. So get the MaxSize reserved for + // this PCD entry. + // + GetPtrTypeSize (TmpTokenNumber, &GetSize); + } + CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize); + FreePool (Data); + } + // + // If the operation is successful, we copy the data + // to the default value buffer in the PCD Database. + // So that we can free the Data allocated in GetHiiVariable. + // + // + // If the operation is not successful, + // Return 1) either the default value specified by Platform Integrator + // 2) Or the value Set by a PCD set operation. + // + RetPtr = (VOID *) VaraiableDefaultBuffer; + break; case PCD_TYPE_STRING: StringTableIdx = (UINT16) *((UINT8 *) PcdDb + Offset); - return (VOID *) &StringTable[StringTableIdx]; + RetPtr = (VOID *) &StringTable[StringTableIdx]; + break; case PCD_TYPE_DATA: - return (VOID *) ((UINT8 *) PcdDb + Offset); + RetPtr = (VOID *) ((UINT8 *) PcdDb + Offset); break; default: @@ -94,85 +160,228 @@ GetWorkerByLocalTokenNumber ( } - ASSERT (FALSE); - - return NULL; -} + EfiReleaseLock (&mPcdDatabaseLock); -VOID * -GetWorker ( - UINTN TokenNumber - ) + return RetPtr; + +} + + + +EFI_STATUS +DxeRegisterCallBackWorker ( + IN UINTN TokenNumber, + IN CONST GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction +) { - UINT32 *LocalTokenNumberTable; - UINT16 *SizeTable; - BOOLEAN IsPeiDb; + CALLBACK_FN_ENTRY *FnTableEntry; + LIST_ENTRY *ListHead; + LIST_ENTRY *ListNode; - ASSERT (TokenNumber < PCD_TOTAL_TOKEN_NUMBER); - - IsPeiDb = (TokenNumber <= PEI_LOCAL_TOKEN_NUMBER) ? TRUE : FALSE; + 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--; - LocalTokenNumberTable = IsPeiDb ? gPcdDatabase->PeiDb.Init.LocalTokenNumberTable : - gPcdDatabase->DxeDb.Init.LocalTokenNumberTable; + ListHead = &mCallbackFnTable[TokenNumber]; + ListNode = GetFirstNode (ListHead); - SizeTable = IsPeiDb ? gPcdDatabase->PeiDb.Init.SizeTable: - gPcdDatabase->DxeDb.Init.SizeTable; + while (ListNode != ListHead) { + FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node); - TokenNumber = IsPeiDb ? TokenNumber : - TokenNumber - PEI_LOCAL_TOKEN_NUMBER; - return GetWorkerByLocalTokenNumber (LocalTokenNumberTable[TokenNumber], IsPeiDb, SizeTable[TokenNumber]); + 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; } + EFI_STATUS -DxeRegisterCallBackWorker ( +DxeUnRegisterCallBackWorker ( IN UINTN TokenNumber, IN CONST GUID *Guid, OPTIONAL - IN PCD_PROTOCOL_CALLBACK CallBackFunction, - IN BOOLEAN Register + IN PCD_PROTOCOL_CALLBACK CallBackFunction ) { - - return EFI_SUCCESS; + 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--; + + ListHead = &mCallbackFnTable[TokenNumber]; + ListNode = GetFirstNode (ListHead); + + 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 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 EFI_INVALID_PARAMETER; } + EFI_STATUS -DxeGetNextTokenWorker ( - IN OUT UINTN *TokenNumber, - IN CONST GUID *Guid OPTIONAL +ExGetNextTokeNumber ( + IN CONST EFI_GUID *Guid, + IN OUT UINTN *TokenNumber, + IN EFI_GUID *GuidTable, + IN UINTN SizeOfGuidTable, + IN DYNAMICEX_MAPPING *ExMapTable, + IN UINTN SizeOfExMapTable ) { - return EFI_SUCCESS; + EFI_GUID *MatchGuid; + UINTN Idx; + UINTN GuidTableIdx; + BOOLEAN Found; + + MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid); + if (MatchGuid == NULL) { + return EFI_NOT_FOUND; + } + + Found = FALSE; + GuidTableIdx = MatchGuid - GuidTable; + for (Idx = 0; Idx < SizeOfExMapTable; Idx++) { + if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) { + Found = TRUE; + break; + } + } + + if (Found) { + if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) { + *TokenNumber = ExMapTable[Idx].ExTokenNumber; + return EFI_SUCCESS; + } + + for ( ; Idx < SizeOfExMapTable; Idx++) { + if (ExMapTable[Idx].ExTokenNumber == *TokenNumber) { + Idx++; + if (Idx == SizeOfExMapTable) { + // + // Exceed the length of ExMap Table + // + *TokenNumber = PCD_INVALID_TOKEN_NUMBER; + return EFI_SUCCESS; + } else if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) { + // + // Found the next match + // + *TokenNumber = ExMapTable[Idx].ExTokenNumber; + return EFI_SUCCESS; + } else { + // + // Guid has been changed. It is the next Token Space Guid. + // We should flag no more TokenNumber. + // + *TokenNumber = PCD_INVALID_TOKEN_NUMBER; + return EFI_SUCCESS; + } + } + } + } + + return EFI_NOT_FOUND; } + VOID BuildPcdDxeDataBase ( VOID -) + ) { PEI_PCD_DATABASE *PeiDatabase; EFI_HOB_GUID_TYPE *GuidHob; + UINTN Idx; - gPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE)); - ASSERT (gPcdDatabase != NULL); + mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE)); + ASSERT (mPcdDatabase != NULL); GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); - ASSERT (GuidHob != NULL); + 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)); + } - PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob); // - // Copy PCD Entries refereneced in PEI phase to PCD DATABASE + // Copy PCD Entries with default value to PCD DATABASE // - CopyMem (&gPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE)); + CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT)); + // - // Copy PCD Entries with default value to PCD DATABASE + // Initialized the Callback Function Table // - CopyMem (&gPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT)); + + mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER * sizeof (LIST_ENTRY)); + + // EBC compiler is very choosy. It may report warning about comparison + // between UINTN and 0 . So we add 1 in each size of the + // comparison. + for (Idx = 0; Idx + 1 < PCD_TOTAL_TOKEN_NUMBER + 1; Idx++) { + InitializeListHead (&mCallbackFnTable[Idx]); + } return; } @@ -183,37 +392,44 @@ EFI_STATUS GetHiiVariable ( IN EFI_GUID *VariableGuid, IN UINT16 *VariableName, - OUT VOID ** VariableData, + OUT UINT8 **VariableData, OUT UINTN *VariableSize ) { UINTN Size; EFI_STATUS Status; - VOID *Buffer; + UINT8 *Buffer; - Status = EfiGetVariable ( + Size = 0; + Buffer = NULL; + + Status = gRT->GetVariable ( (UINT16 *)VariableName, VariableGuid, NULL, &Size, - NULL - ); - ASSERT (Status == EFI_BUFFER_TOO_SMALL); - - Buffer = AllocatePool (Size); - - ASSERT (Buffer != NULL); - - Status = EfiGetVariable ( - VariableName, - VariableGuid, - NULL, - &Size, Buffer ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + Buffer = (UINT8 *) AllocatePool (Size); + + ASSERT (Buffer != NULL); + + Status = gRT->GetVariable ( + VariableName, + VariableGuid, + NULL, + &Size, + Buffer + ); + + ASSERT (Status == EFI_SUCCESS); + *VariableData = Buffer; + *VariableSize = Size; + } return Status; - } @@ -233,36 +449,40 @@ GetSkuEnabledTokenNumber ( ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0); - PcdDb = IsPeiDb ? (UINT8 *) &gPcdDatabase->PeiDb : (UINT8 *) &gPcdDatabase->DxeDb; + PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb; SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK)); Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset); - PhaseSkuIdTable = IsPeiDb ? gPcdDatabase->PeiDb.Init.SkuIdTable : - gPcdDatabase->DxeDb.Init.SkuIdTable; + PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable : + mPcdDatabase->DxeDb.Init.SkuIdTable; SkuIdTable = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset]; for (i = 0; i < SkuIdTable[0]; i++) { - if (gPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[i + 1]) { + if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[i + 1]) { break; } } ASSERT (i < SkuIdTable[0]); - switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) { + switch (LocalTokenNumber & PCD_TYPE_ALL_SET) { case PCD_TYPE_VPD: Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]); - return ((Value - PcdDb) | PCD_TYPE_VPD); + return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD); case PCD_TYPE_HII: Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]); - return ((Value - PcdDb) | PCD_TYPE_HII); + return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII); + + case PCD_TYPE_STRING: + Value = (UINT8 *) &(((STRING_HEAD *) Value)[i]); + return (UINT32) ((Value - PcdDb) | PCD_TYPE_STRING); case PCD_TYPE_DATA: Value += Size * i; - return (Value - PcdDb); - + return (UINT32) (Value - PcdDb); + default: ASSERT (FALSE); } @@ -286,195 +506,271 @@ InvokeCallbackOnSet ( UINTN Size ) { - return; -} - - - - -EFI_STATUS -SetWorker ( - UINTN TokenNumber, - VOID *Data, - UINTN Size, - BOOLEAN PtrType - ) -{ - UINT32 *LocalTokenNumberTable; - BOOLEAN IsPeiDb; - - - ASSERT (TokenNumber < PCD_TOTAL_TOKEN_NUMBER); + CALLBACK_FN_ENTRY *FnTableEntry; + LIST_ENTRY *ListHead; + LIST_ENTRY *ListNode; - if (PtrType) { - ASSERT (Size <= DxePcdGetSize (TokenNumber)); - } else { - ASSERT (Size == DxePcdGetSize (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--; - IsPeiDb = (TokenNumber <= PEI_LOCAL_TOKEN_NUMBER) ? TRUE : FALSE; + ListHead = &mCallbackFnTable[TokenNumber]; + ListNode = GetFirstNode (ListHead); - LocalTokenNumberTable = IsPeiDb ? gPcdDatabase->PeiDb.Init.LocalTokenNumberTable : - gPcdDatabase->DxeDb.Init.LocalTokenNumberTable; + while (ListNode != ListHead) { + FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node); - TokenNumber = IsPeiDb ? TokenNumber - : TokenNumber - PEI_LOCAL_TOKEN_NUMBER; + FnTableEntry->CallbackFn(Guid, + (Guid == NULL) ? TokenNumber : ExTokenNumber, + Data, + Size); + + ListNode = GetNextNode (ListHead, ListNode); + } - InvokeCallbackOnSet (0, NULL, TokenNumber, Data, Size); - - return SetWorkerByLocalTokenNumber (LocalTokenNumberTable[TokenNumber], Data, Size, PtrType, IsPeiDb); - -} - - - - - -VOID * -ExGetWorker ( - IN CONST EFI_GUID *Guid, - IN UINTN ExTokenNumber, - IN UINTN GetSize - ) -{ - EX_PCD_ENTRY_ATTRIBUTE Attr; - - GetExPcdTokenAttributes (Guid, ExTokenNumber, &Attr); - - ASSERT ((GetSize == Attr.Size) || (GetSize == 0)); - - return GetWorkerByLocalTokenNumber (Attr.LocalTokenNumberAlias, - Attr.IsPeiDb, - Attr.Size - ); + return; } - - - EFI_STATUS -ExSetWorker ( - IN UINT32 ExTokenNumber, - IN CONST EFI_GUID *Guid, - VOID *Data, - UINTN SetSize, - BOOLEAN PtrType +SetValueWorker ( + IN UINTN TokenNumber, + IN VOID *Data, + IN UINTN Size ) { - EX_PCD_ENTRY_ATTRIBUTE Attr; - - GetExPcdTokenAttributes (Guid, ExTokenNumber, &Attr); - - ASSERT (!PtrType && (SetSize == Attr.Size)); - - ASSERT (PtrType && (SetSize <= Attr.Size)); - - InvokeCallbackOnSet (ExTokenNumber, Guid, Attr.TokenNumber, Data, Attr.Size); - - SetWorkerByLocalTokenNumber (Attr.LocalTokenNumberAlias, Data, Attr.Size, PtrType, Attr.IsPeiDb); - - return EFI_SUCCESS; - + return SetWorker (TokenNumber, Data, &Size, FALSE); } - - EFI_STATUS -SetWorkerByLocalTokenNumber ( - UINT32 LocalTokenNumber, - VOID *Data, - UINTN Size, - BOOLEAN PtrType, - BOOLEAN IsPeiDb +SetWorker ( + IN UINTN TokenNumber, + IN VOID *Data, + IN OUT UINTN *Size, + IN BOOLEAN PtrType ) { + 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; + EFI_STATUS Status; + UINTN MaxSize; + UINTN TmpTokenNumber; + // + // Aquire lock to prevent reentrance from TPL_CALLBACK level + // + EfiAcquireLock (&mPcdDatabaseLock); + + // + // 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--; + + TmpTokenNumber = TokenNumber; + + // EBC compiler is very choosy. It may report warning about comparison + // between UINTN and 0 . So we add 1 in each size of the + // comparison. + ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1); + + if (!PtrType) { + ASSERT (*Size == DxePcdGetSize (TokenNumber + 1)); + } + + // EBC compiler is very choosy. It may report warning about comparison + // between UINTN and 0 . So we add 1 in each size of the + // comparison. + IsPeiDb = (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE; + + LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : + mPcdDatabase->DxeDb.Init.LocalTokenNumberTable; + + // EBC compiler is very choosy. It may report warning about comparison + // between UINTN and 0 . So we add 1 in each size of the + // comparison. + if ((TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) || + (TokenNumber + 1 >= PEI_LOCAL_TOKEN_NUMBER + 1 || TokenNumber + 1 < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1))) { + InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size); + } + + TokenNumber = IsPeiDb ? TokenNumber + : TokenNumber - PEI_LOCAL_TOKEN_NUMBER; + + LocalTokenNumber = LocalTokenNumberTable[TokenNumber]; + if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) { - LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size, IsPeiDb); + if (PtrType) { + GetPtrTypeSize (TmpTokenNumber, &MaxSize); + } else { + MaxSize = *Size; + } + LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb); } Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK; - PcdDb = IsPeiDb ? ((UINT8 *) &gPcdDatabase->PeiDb) : ((UINT8 *) &gPcdDatabase->DxeDb); + PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb); - StringTable = IsPeiDb ? gPcdDatabase->PeiDb.Init.StringTable : - gPcdDatabase->DxeDb.Init.StringTable; + StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable : + mPcdDatabase->DxeDb.Init.StringTable; InternalData = PcdDb + Offset; - switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) { + switch (LocalTokenNumber & PCD_TYPE_ALL_SET) { case PCD_TYPE_VPD: ASSERT (FALSE); - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + break; case PCD_TYPE_STRING: - CopyMem (&StringTable[*((UINT16 *)InternalData)], Data, Size); + if (SetPtrTypeSize (TmpTokenNumber, Size)) { + CopyMem (&StringTable[*((UINT16 *)InternalData)], Data, *Size); + Status = EFI_SUCCESS; + } else { + Status = EFI_INVALID_PARAMETER; + } break; case PCD_TYPE_HII: - // - // Bug Bug: Please implement this - // - GuidTable = IsPeiDb ? gPcdDatabase->PeiDb.Init.GuidTable : - gPcdDatabase->DxeDb.Init.GuidTable; + if (PtrType) { + if (!SetPtrTypeSize (TmpTokenNumber, Size)) { + Status = EFI_INVALID_PARAMETER; + break; + } + } + + 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; - return EFI_SUCCESS; + Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset); + if (EFI_NOT_FOUND == Status) { + CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size); + Status = EFI_SUCCESS; + } + break; + case PCD_TYPE_DATA: if (PtrType) { - CopyMem (InternalData, Data, Size); - return EFI_SUCCESS; + if (SetPtrTypeSize (TmpTokenNumber, Size)) { + CopyMem (InternalData, Data, *Size); + Status = EFI_SUCCESS; + } else { + Status = EFI_INVALID_PARAMETER; + } + break; } - switch (Size) { + Status = EFI_SUCCESS; + switch (*Size) { case sizeof(UINT8): *((UINT8 *) InternalData) = *((UINT8 *) Data); - return EFI_SUCCESS; + break; case sizeof(UINT16): *((UINT16 *) InternalData) = *((UINT16 *) Data); - return EFI_SUCCESS; + break; case sizeof(UINT32): *((UINT32 *) InternalData) = *((UINT32 *) Data); - return EFI_SUCCESS; + break; case sizeof(UINT64): *((UINT64 *) InternalData) = *((UINT64 *) Data); - return EFI_SUCCESS; + break; default: ASSERT (FALSE); - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + break; } + break; default: ASSERT (FALSE); + Status = EFI_NOT_FOUND; break; } - - ASSERT (FALSE); - return EFI_NOT_FOUND; + + EfiReleaseLock (&mPcdDatabaseLock); + + return Status; } + + +VOID * +ExGetWorker ( + IN CONST EFI_GUID *Guid, + IN UINTN ExTokenNumber, + IN UINTN GetSize + ) +{ + return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize); +} + + + + +EFI_STATUS +ExSetValueWorker ( + IN UINTN ExTokenNumber, + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN SetSize + ) +{ + return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE); +} + + +EFI_STATUS +ExSetWorker ( + IN UINTN ExTokenNumber, + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN OUT UINTN *SetSize, + IN BOOLEAN PtrType + ) +{ + UINTN TokenNumber; + + TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber); + + InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize); + + return SetWorker (TokenNumber, Data, SetSize, PtrType); + +} + + + + EFI_STATUS SetHiiVariable ( IN EFI_GUID *VariableGuid, @@ -491,95 +787,371 @@ SetHiiVariable ( Size = 0; - Status = EfiGetVariable ( + Status = gRT->GetVariable ( (UINT16 *)VariableName, VariableGuid, - &Attribute, + NULL, &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, - &Attribute, - &Size, - Buffer - ); + Status = gRT->GetVariable ( + VariableName, + VariableGuid, + &Attribute, + &Size, + Buffer + ); + + ASSERT_EFI_ERROR (Status); + CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize); - CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize); + Status = gRT->SetVariable ( + VariableName, + VariableGuid, + Attribute, + Size, + Buffer + ); - return EfiSetVariable ( - VariableName, - VariableGuid, - Attribute, - Size, - Buffer - ); + FreePool (Buffer); + return Status; + } + + // + // If we drop to here, we don't have a Variable entry in + // the variable service yet. So, we will save the data + // in the PCD Database's volatile area. + // + return Status; } -VOID -GetExPcdTokenAttributes ( +UINTN +GetExPcdTokenNumber ( IN CONST EFI_GUID *Guid, - IN UINT32 ExTokenNumber, - OUT EX_PCD_ENTRY_ATTRIBUTE *ExAttr + IN UINT32 ExTokenNumber ) { UINT32 i; DYNAMICEX_MAPPING *ExMap; EFI_GUID *GuidTable; - UINT16 *SizeTable; + EFI_GUID *MatchGuid; + UINTN MatchGuidIdx; - ExMap = gPcdDatabase->PeiDb.Init.ExMapTable; - GuidTable = gPcdDatabase->PeiDb.Init.GuidTable; - SizeTable = gPcdDatabase->PeiDb.Init.SizeTable; - - for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) { - if ((ExTokenNumber == ExMap[i].ExTokenNumber) && - CompareGuid (Guid, (CONST EFI_GUID *) &GuidTable[ExMap[i].ExGuidIndex]) - ) { + if (!PEI_DATABASE_EMPTY) { + ExMap = mPcdDatabase->PeiDb.Init.ExMapTable; + GuidTable = mPcdDatabase->PeiDb.Init.GuidTable; + + MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid); + + if (MatchGuid != NULL) { - ExAttr->IsPeiDb = TRUE; - ExAttr->Size = SizeTable[i + PEI_NEX_TOKEN_NUMBER]; - ExAttr->TokenNumber = i + PEI_NEX_TOKEN_NUMBER; - ExAttr->LocalTokenNumberAlias = ExMap[i].LocalTokenNumber; - return; + 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 = gPcdDatabase->DxeDb.Init.ExMapTable; - GuidTable = gPcdDatabase->DxeDb.Init.GuidTable; - SizeTable = gPcdDatabase->DxeDb.Init.SizeTable; + ExMap = mPcdDatabase->DxeDb.Init.ExMapTable; + GuidTable = mPcdDatabase->DxeDb.Init.GuidTable; + + MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid); + // + // We need to ASSERT here. If GUID can't be found in GuidTable, this is a + // error in the BUILD system. + // + ASSERT (MatchGuid != NULL); + + MatchGuidIdx = MatchGuid - GuidTable; for (i = 0; i < DXE_EXMAPPING_TABLE_SIZE; i++) { if ((ExTokenNumber == ExMap[i].ExTokenNumber) && - CompareGuid (Guid, (CONST EFI_GUID *) &GuidTable[ExMap[i].ExGuidIndex]) - ) { + (MatchGuidIdx == ExMap[i].ExGuidIndex)) { + return ExMap[i].LocalTokenNumber; + } + } + + ASSERT (FALSE); + + return 0; +} + + + +SKU_ID * +GetSkuIdArray ( + IN UINTN LocalTokenNumberTableIdx, + IN BOOLEAN IsPeiPcd + ) +{ + SKU_HEAD *SkuHead; + UINTN LocalTokenNumber; + UINT8 *Database; + + if (IsPeiPcd) { + LocalTokenNumber = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx]; + Database = (UINT8 *) &mPcdDatabase->PeiDb; + } else { + LocalTokenNumber = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx - PEI_LOCAL_TOKEN_NUMBER]; + Database = (UINT8 *) &mPcdDatabase->DxeDb; + } + + ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0); + + SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK)); + + return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset); + +} + + + +UINTN +GetSizeTableIndexA ( + IN UINTN LocalTokenNumberTableIdx, + IN UINT32 *LocalTokenNumberTable, + IN BOOLEAN IsPeiDb + ) +{ + UINTN i; + UINTN SizeTableIdx; + UINTN LocalTokenNumber; + SKU_ID *SkuIdTable; + + SizeTableIdx = 0; - ExAttr->IsPeiDb = FALSE; - ExAttr->Size = SizeTable[i + DXE_NEX_TOKEN_NUMBER]; - ExAttr->TokenNumber = i + DXE_NEX_TOKEN_NUMBER; - ExAttr->LocalTokenNumberAlias = ExMap[i].LocalTokenNumber; - return; + for (i=0; iPeiDb.Init.LocalTokenNumberTable; + } else { + LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable; + } + return GetSizeTableIndexA (LocalTokenNumberTableIdx, + LocalTokenNumberTable, + IsPeiDb); +} + + + +UINTN +GetPtrTypeSize ( + IN UINTN LocalTokenNumberTableIdx, + OUT UINTN *MaxSize + ) +{ + INTN SizeTableIdx; + UINTN LocalTokenNumber; + SKU_ID *SkuIdTable; + SIZE_INFO *SizeTable; + UINTN i; + BOOLEAN IsPeiDb; + UINT32 *LocalTokenNumberTable; + + // EBC compiler is very choosy. It may report warning about comparison + // between UINTN and 0 . So we add 1 in each size of the + // comparison. + IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1); + + + if (IsPeiDb) { + LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable; + SizeTable = mPcdDatabase->PeiDb.Init.SizeTable; + } else { + LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER; + LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable; + SizeTable = mPcdDatabase->DxeDb.Init.SizeTable; + } + + LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx]; + + ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER); + + SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb); + + *MaxSize = SizeTable[SizeTableIdx]; + // + // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type + // PCD entry. + // + if (LocalTokenNumber & PCD_TYPE_VPD) { + // + // We have only one entry for VPD enabled PCD entry: + // 1) MAX Size. + // We consider current size is equal to MAX size. + // + return *MaxSize; + } else { + if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) { + // + // We have only two entry for Non-Sku enabled PCD entry: + // 1) MAX SIZE + // 2) Current Size + // + return SizeTable[SizeTableIdx + 1]; + } else { + // + // We have these entry for SKU enabled PCD entry + // 1) MAX SIZE + // 2) Current Size for each SKU_ID (It is equal to MaxSku). + // + SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb); + for (i = 0; i < SkuIdTable[0]; i++) { + if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) { + return SizeTable[SizeTableIdx + 1 + i]; + } + } + return SizeTable[SizeTableIdx + 1]; + } + } +} + + + +BOOLEAN +SetPtrTypeSize ( + IN UINTN LocalTokenNumberTableIdx, + IN OUT UINTN *CurrentSize + ) +{ + INTN SizeTableIdx; + UINTN LocalTokenNumber; + SKU_ID *SkuIdTable; + SIZE_INFO *SizeTable; + UINTN i; + UINTN MaxSize; + BOOLEAN IsPeiDb; + UINT32 *LocalTokenNumberTable; + + // EBC compiler is very choosy. It may report warning about comparison + // between UINTN and 0 . So we add 1 in each size of the + // comparison. + IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1); + + if (IsPeiDb) { + LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable; + SizeTable = mPcdDatabase->PeiDb.Init.SizeTable; + } else { + LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER; + LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable; + SizeTable = mPcdDatabase->DxeDb.Init.SizeTable; + } + + LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx]; + + ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER); + + SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb); + + MaxSize = SizeTable[SizeTableIdx]; + // + // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type + // PCD entry. + // + if (LocalTokenNumber & PCD_TYPE_VPD) { + // + // We shouldn't come here as we don't support SET for VPD + // + ASSERT (FALSE); + return FALSE; + } else { + if ((*CurrentSize > MaxSize) || + (*CurrentSize == MAX_ADDRESS)) { + *CurrentSize = MaxSize; + return FALSE; + } + + if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) { + // + // We have only two entry for Non-Sku enabled PCD entry: + // 1) MAX SIZE + // 2) Current Size + // + SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize; + return TRUE; + } else { + // + // We have these entry for SKU enabled PCD entry + // 1) MAX SIZE + // 2) Current Size for each SKU_ID (It is equal to MaxSku). + // + SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb); + for (i = 0; i < SkuIdTable[0]; i++) { + if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) { + SizeTable[SizeTableIdx + 1 + i] = (SIZE_INFO) *CurrentSize; + return TRUE; + } + } + SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize; + return TRUE; + } + } }