EFI_GUID *Guid;\r
UINT16 *Name;\r
UINTN VariableOffset;\r
+ UINT32 Attributes;\r
VOID *InternalData;\r
VARIABLE_HEAD *VariableHead;\r
UINTN Offset;\r
Guid = GuidTable + VariableHead->GuidTableIndex;\r
Name = (UINT16*) (StringTable + VariableHead->StringIndex);\r
VariableOffset = VariableHead->Offset;\r
- Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset);\r
-\r
- if (EFI_NOT_FOUND == Status) {\r
- if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {\r
- CopyMem (\r
- StringTable + *(STRING_HEAD *)(PcdDb + VariableHead->DefaultValueOffset),\r
- Data,\r
- *Size\r
- );\r
- } else {\r
- CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size);\r
- } \r
- Status = EFI_SUCCESS;\r
- }\r
+ Attributes = VariableHead->Attributes;\r
+ Status = SetHiiVariable (Guid, Name, Attributes, Data, *Size, VariableOffset);\r
break;\r
\r
case PCD_TYPE_DATA:\r
\r
@param VariableGuid Guid of variable which stored value of a HII-type PCD.\r
@param VariableName Unicode name of variable which stored value of a HII-type PCD.\r
+ @param SetAttributes Attributes bitmask to set for the variable.\r
@param Data Value want to be set.\r
@param DataSize Size of value\r
@param Offset Value offset of HII-type PCD in variable.\r
SetHiiVariable (\r
IN EFI_GUID *VariableGuid,\r
IN UINT16 *VariableName,\r
+ IN UINT32 SetAttributes,\r
IN CONST VOID *Data,\r
IN UINTN DataSize,\r
IN UINTN Offset\r
//\r
// Patch new PCD's value to offset in given HII variable.\r
//\r
- if (Size >= (DataSize + Offset)) {\r
+ if (Size >= (DataSize + Offset)) {\r
SetSize = Size;\r
} else {\r
SetSize = DataSize + Offset;\r
\r
CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
\r
+ if (SetAttributes == 0) {\r
+ SetAttributes = Attribute;\r
+ }\r
+\r
Status = gRT->SetVariable (\r
VariableName,\r
VariableGuid,\r
- Attribute,\r
+ SetAttributes,\r
SetSize,\r
Buffer\r
);\r
ASSERT (Buffer != NULL);\r
\r
CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
- \r
+\r
+ if (SetAttributes == 0) {\r
+ SetAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
+ }\r
+\r
Status = gRT->SetVariable (\r
VariableName,\r
VariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ SetAttributes,\r
Size,\r
Buffer\r
);\r
}\r
\r
//\r
- // If we drop to here, the value is failed to be written in to variable area\r
- // So, we will save the data in the PCD Database's volatile area.\r
+ // If we drop to here, the value is failed to be written in to variable area.\r
//\r
return Status;\r
}\r
}\r
}\r
}\r
+\r
+/**\r
+ VariableLock DynamicHiiPcd.\r
+\r
+ @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,\r
+ If FALSE, the pcd entry is initialized in DXE phase.\r
+ @param[in] VariableLock Pointer to VariableLockProtocol.\r
+\r
+**/\r
+VOID\r
+VariableLockDynamicHiiPcd (\r
+ IN BOOLEAN IsPeiDb,\r
+ IN EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCD_DATABASE_INIT *Database;\r
+ UINT32 LocalTokenCount; \r
+ UINTN TokenNumber;\r
+ UINT32 LocalTokenNumber;\r
+ UINTN Offset;\r
+ EFI_GUID *GuidTable;\r
+ UINT8 *StringTable;\r
+ VARIABLE_HEAD *VariableHead;\r
+ EFI_GUID *Guid;\r
+ UINT16 *Name;\r
+\r
+ Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;\r
+ LocalTokenCount = IsPeiDb ? mPeiLocalTokenCount: mDxeLocalTokenCount;\r
+\r
+ //\r
+ // Go through PCD database to find out DynamicHii PCDs.\r
+ //\r
+ for (TokenNumber = 0; TokenNumber < LocalTokenCount; TokenNumber++) {\r
+ if (IsPeiDb) {\r
+ LocalTokenNumber = GetLocalTokenNumber (TRUE, TokenNumber);\r
+ } else {\r
+ LocalTokenNumber = GetLocalTokenNumber (FALSE, TokenNumber + mPeiLocalTokenCount);\r
+ }\r
+ if ((LocalTokenNumber & PCD_TYPE_HII) != 0) {\r
+ Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
+ VariableHead = (VARIABLE_HEAD *) ((UINT8 *) Database + Offset);\r
+ //\r
+ // Why not to set property by VarCheckProtocol with Attributes and Property directly here?\r
+ // It is because that set property by VarCheckProtocol will indicate the variable to\r
+ // be a system variable, but the unknown max size of the variable is dangerous to\r
+ // the system variable region.\r
+ //\r
+ if ((VariableHead->Property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) != 0) {\r
+ //\r
+ // DynamicHii PCD with RO property set in *.dsc.\r
+ //\r
+ StringTable = (UINT8 *) ((UINT8 *) Database + Database->StringTableOffset);\r
+ GuidTable = (EFI_GUID *) ((UINT8 *) Database + Database->GuidTableOffset);\r
+ Guid = GuidTable + VariableHead->GuidTableIndex;\r
+ Name = (UINT16*) (StringTable + VariableHead->StringIndex);\r
+ Status = VariableLock->RequestToLock (VariableLock, Name, Guid);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ VariableLockProtocol callback\r
+ to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.\r
+\r
+ @param[in] Event Event whose notification function is being invoked.\r
+ @param[in] Context Pointer to the notification function's context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VariableLockCallBack (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
+\r
+ Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
+ if (!EFI_ERROR (Status)) {\r
+ VariableLockDynamicHiiPcd (TRUE, VariableLock);\r
+ VariableLockDynamicHiiPcd (FALSE, VariableLock);\r
+ }\r
+}\r
+\r