HiiNewPackageList (
  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,
  IN CONST EFI_HII_PACKAGE_LIST_HEADER  *PackageList,
  IN CONST EFI_HANDLE                   DriverHandle, OPTIONAL
  OUT EFI_HII_HANDLE                    *Handle
  )
{
  EFI_STATUS                          Status;
  HII_DATABASE_PRIVATE_DATA           *Private;
  HII_DATABASE_RECORD                 *DatabaseRecord;
  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
  LIST_ENTRY                          *Link;
  EFI_GUID                            PackageListGuid;

  if (This == NULL || PackageList == NULL || Handle == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
  CopyMem (&PackageListGuid, (VOID *) PackageList, sizeof (EFI_GUID));

  //
  // Check the Package list GUID to guarantee this GUID is unique in database.
  //
  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
    if (CompareGuid (
          &(DatabaseRecord->PackageList->PackageListHdr.PackageListGuid),
          &PackageListGuid) &&
        DatabaseRecord->DriverHandle == DriverHandle) {
      return EFI_INVALID_PARAMETER;
    }
  }

  EfiAcquireLock (&mHiiDatabaseLock);

  //
  // Build a PackageList node
  //
  Status = GenerateHiiDatabaseRecord (Private, &DatabaseRecord);
  if (EFI_ERROR (Status)) {
    EfiReleaseLock (&mHiiDatabaseLock);
    return Status;
  }

  //
  // Fill in information of the created Package List node
  // according to incoming package list.
  //
  Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, PackageList, DatabaseRecord);
  if (EFI_ERROR (Status)) {
    EfiReleaseLock (&mHiiDatabaseLock);
    return Status;
  }

  DatabaseRecord->DriverHandle = DriverHandle;

  //
  // Create a Device path package and add into the package list if exists.
  //
  Status = gBS->HandleProtocol (
                  DriverHandle,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &DevicePath
                  );
  if (!EFI_ERROR (Status)) {
    Status = AddDevicePathPackage (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, DevicePath, DatabaseRecord);
    ASSERT_EFI_ERROR (Status);
  }

  *Handle = DatabaseRecord->Handle;

  //
  // Check whether need to get the Database info.
  // Only after ReadyToBoot, need to do the export.
  //
  if (gExportAfterReadyToBoot) {
    HiiGetDatabaseInfo (This);
  }
  EfiReleaseLock (&mHiiDatabaseLock);

  //
  // Notes:
  // HiiGetDatabaseInfo () will get the contents of HII data base,
  // belong to the atomic behavior of Hii Database update.
  // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
  // we can not think it belong to the atomic behavior of Hii Database update.
  // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
  //

  // Check whether need to get the configuration setting info from HII drivers.
  // When after ReadyToBoot and need to do the export for form package add.
  //
  if (gExportAfterReadyToBoot && gExportConfigResp) {
    HiiGetConfigRespInfo (This);
  }

  return EFI_SUCCESS;
}