+/**\r
+ Adjust all string packages in a single package list to have the same max string ID.\r
+ \r
+ @param PackageList Pointer to a package list which will be adjusted.\r
+\r
+ @retval EFI_SUCCESS Adjust all string packages successfully.\r
+ @retval others Can't adjust string packges.\r
+\r
+**/\r
+EFI_STATUS\r
+AdjustStringPackage (\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+)\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
+ UINT32 Skip2BlockSize;\r
+ UINT32 OldBlockSize;\r
+ UINT8 *StringBlock;\r
+ UINT8 *BlockPtr;\r
+ EFI_STRING_ID MaxStringId;\r
+ UINT16 SkipCount;\r
+\r
+ MaxStringId = 0;\r
+ for (Link = PackageList->StringPkgHdr.ForwardLink;\r
+ Link != &PackageList->StringPkgHdr;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+ if (MaxStringId < StringPackage->MaxStringId) {\r
+ MaxStringId = StringPackage->MaxStringId;\r
+ }\r
+ }\r
+\r
+ for (Link = PackageList->StringPkgHdr.ForwardLink;\r
+ Link != &PackageList->StringPkgHdr;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+ if (StringPackage->MaxStringId < MaxStringId) {\r
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
+ //\r
+ // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCKs to reserve the missing string IDs.\r
+ //\r
+ SkipCount = (UINT16) (MaxStringId - StringPackage->MaxStringId);\r
+ Skip2BlockSize = (UINT32) sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
+\r
+ StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Skip2BlockSize);\r
+ if (StringBlock == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Copy original string blocks, except the EFI_HII_SIBT_END.\r
+ //\r
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));\r
+ //\r
+ // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCK blocks\r
+ //\r
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);\r
+ *BlockPtr = EFI_HII_SIBT_SKIP2;\r
+ CopyMem (BlockPtr + 1, &SkipCount, sizeof (UINT16));\r
+ BlockPtr += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
+\r
+ //\r
+ // Append a EFI_HII_SIBT_END block to the end.\r
+ //\r
+ *BlockPtr = EFI_HII_SIBT_END;\r
+ FreePool (StringPackage->StringBlock);\r
+ StringPackage->StringBlock = StringBlock;\r
+ StringPackage->StringPkgHdr->Header.Length += Skip2BlockSize;\r
+ PackageList->PackageListHdr.PackageLength += Skip2BlockSize;\r
+ StringPackage->MaxStringId = MaxStringId;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r