diff --git a/Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.dec b/Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.dec
new file mode 100644
index 000000000000..4b8b2e047ed9
--- /dev/null
+++ b/Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.dec
@@ -0,0 +1,32 @@
+#
+#  Copyright (c) 2018, Linaro Limited. All rights reserved.
+#
+#  This program and the accompanying materials are licensed and made available
+#  under the terms and conditions of the BSD License which accompanies this
+#  distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+[Defines]
+  DEC_SPECIFICATION              = 0x00010019
+  PACKAGE_NAME                   = UsbSerialNumberPkg
+  PACKAGE_GUID                   = dcd67420-4220-4b01-a8ba-1fa97fda1678
+  PACKAGE_VERSION                = 0.1
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+#                   Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+[Includes.common]
+  Include                        # Root include for the package
+
+[Guids.common]
+  gUsbSerialNumberTokenSpaceGuid = { 0x0572f26b, 0x1a88, 0x49c2, { 0xb6, 0x98, 0x4d, 0xe0, 0xd0, 0x2a, 0xfe, 0x09 } }
diff --git a/Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.inf b/Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.inf
new file mode 100644
index 000000000000..70ea086d324e
--- /dev/null
+++ b/Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.inf
@@ -0,0 +1,45 @@
+#/** @file
+#
+#  Copyright (c) 2018, Linaro. All rights reserved.
+#
+#  This program and the accompanying materials are licensed and made available
+#  under the terms and conditions of the BSD License which accompanies this
+#  distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010019
+  BASE_NAME                      = UsbSerialNumberLib
+  FILE_GUID                      = 88709c56-2a76-4a13-8bcf-427970b7e32a
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = UsbSerialNumberLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+  VALID_ARCHITECTURES           = ARM AARCH64
+
+[Sources]
+  UsbSerialNumberLib.c
+
+[LibraryClasses]
+  ArmGenericTimerCounterLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiLib
+
+[Protocols]
+  gEfiBlockIoProtocolGuid
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdePkg/MdePkg.dec
+  Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.dec
diff --git a/Platform/Hisilicon/Library/UsbSerialNumberLib/Include/Library/UsbSerialNumberLib.h b/Platform/Hisilicon/Library/UsbSerialNumberLib/Include/Library/UsbSerialNumberLib.h
new file mode 100644
index 000000000000..d3307153ff11
--- /dev/null
+++ b/Platform/Hisilicon/Library/UsbSerialNumberLib/Include/Library/UsbSerialNumberLib.h
@@ -0,0 +1,59 @@
+/** @file
+
+  Copyright (c) 2017, Linaro. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __USB_SERIAL_NUMBER_LIB_H__
+#define __USB_SERIAL_NUMBER_LIB_H__
+
+#include <Uefi.h>
+
+#define SERIAL_NUMBER_SIZE                      17
+
+typedef struct {
+  UINT64        Magic;
+  UINT64        Data;
+  CHAR16        UnicodeSN[SERIAL_NUMBER_SIZE];
+} RANDOM_SERIAL_NUMBER;
+
+EFI_STATUS
+GenerateUsbSNBySeed (
+  IN  UINT32                  Seed,
+  OUT RANDOM_SERIAL_NUMBER   *RandomSN
+  );
+
+EFI_STATUS
+GenerateUsbSN (
+  OUT CHAR16                 *UnicodeSN
+  );
+
+EFI_STATUS
+AssignUsbSN (
+  IN  CHAR8                  *AsciiCmd,
+  OUT CHAR16                 *UnicodeSN
+  );
+
+EFI_STATUS
+LoadSNFromBlock (
+  IN  EFI_HANDLE              FlashHandle,
+  IN  EFI_LBA                 Lba,
+  OUT CHAR16                 *UnicodeSN
+  );
+
+EFI_STATUS
+StoreSNToBlock (
+  IN EFI_HANDLE               FlashHandle,
+  IN EFI_LBA                  Lba,
+  IN CHAR16                  *UnicodeSN
+  );
+
+#endif /* __USB_SERIAL_NUMBER_LIB_H__ */
diff --git a/Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.c b/Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.c
new file mode 100644
index 000000000000..98552f5f72fc
--- /dev/null
+++ b/Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.c
@@ -0,0 +1,341 @@
+/** @file
+
+  Copyright (c) 2018, Linaro. All rights reserved.
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License which accompanies this
+  distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/ArmGenericTimerCounterLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UsbSerialNumberLib.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+
+#define SERIAL_NUMBER_LEN                16
+#define SERIAL_NUMBER_SIZE               17
+
+#define RANDOM_MAX                       0x7FFFFFFFFFFFFFFF
+#define RANDOM_MAGIC                     0x9A4DBEAF
+
+STATIC
+EFI_STATUS
+GenerateRandomData (
+  IN  UINT32              Seed,
+  OUT UINT64              *RandomData
+  )
+{
+  INT64                   Quotient, Remainder, Tmp;
+
+  if (RandomData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  Quotient = (INT64) Seed / 127773;
+  Remainder = (INT64) Seed % 127773;
+  Tmp = (16807 * Remainder) - (2836 * Quotient);
+  if (Tmp < 0) {
+    Tmp += RANDOM_MAX;
+  }
+  Tmp = Tmp % ((UINT64)RANDOM_MAX + 1);
+  *RandomData = (UINT64)Tmp;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GenerateUsbSNBySeed (
+  IN  UINT32                  Seed,
+  OUT RANDOM_SERIAL_NUMBER    *RandomSN
+  )
+{
+  EFI_STATUS               Status;
+  UINT64                   Tmp;
+
+  if (RandomSN == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  ZeroMem (RandomSN, sizeof (RANDOM_SERIAL_NUMBER));
+  Status = GenerateRandomData (Seed, &Tmp);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  RandomSN->Data = (Tmp << 32) | Seed;
+  UnicodeSPrint (
+    RandomSN->UnicodeSN,
+    SERIAL_NUMBER_SIZE * sizeof (CHAR16),
+    L"%lx",
+    RandomSN->Data
+    );
+  RandomSN->Magic = RANDOM_MAGIC;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GenerateUsbSN (
+  OUT CHAR16                  *UnicodeSN
+  )
+{
+  EFI_STATUS               Status;
+  UINT64                   Tmp;
+  UINT32                   Seed;
+  RANDOM_SERIAL_NUMBER     RandomSN;
+
+  if (UnicodeSN == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  ZeroMem (&RandomSN, sizeof (RANDOM_SERIAL_NUMBER));
+  Seed = ArmGenericTimerGetSystemCount ();
+  Status = GenerateRandomData (Seed, &Tmp);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  RandomSN.Data = (Tmp << 32) | Seed;
+  UnicodeSPrint (
+    RandomSN.UnicodeSN,
+    SERIAL_NUMBER_SIZE * sizeof (CHAR16),
+    L"%lx",
+    RandomSN.Data
+    );
+  StrCpyS (UnicodeSN, SERIAL_NUMBER_SIZE * sizeof (CHAR16), RandomSN.UnicodeSN);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AssignUsbSN (
+  IN  CHAR8                   *AsciiCmd,
+  OUT CHAR16                  *UnicodeSN
+  )
+{
+  CHAR8                       Data;
+  UINTN                       Index;
+  RANDOM_SERIAL_NUMBER        RandomSN;
+
+  if ((AsciiCmd == NULL) || (UnicodeSN == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+  for (Index = 0; Index < SERIAL_NUMBER_LEN; Index++) {
+    Data = *(AsciiCmd + Index);
+    if (((Data >= '0') && (Data <= '9')) ||
+        ((Data >= 'A') && (Data <= 'F'))) {
+      continue;
+    }
+    //
+    // Always use with upper case
+    //
+    if ((Data >= 'a') && (Data <= 'f')) {
+      *(AsciiCmd + Index) = Data - 'a' + 'A';
+      continue;
+    }
+    if (Data == '\0') {
+      break;
+    }
+    return EFI_INVALID_PARAMETER;
+  }
+  ZeroMem (&RandomSN, sizeof (RANDOM_SERIAL_NUMBER));
+  AsciiStrToUnicodeStr (AsciiCmd, RandomSN.UnicodeSN);
+  StrCpyS (UnicodeSN, SERIAL_NUMBER_SIZE * sizeof (CHAR16), RandomSN.UnicodeSN);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+LoadSNFromBlock (
+  IN  EFI_HANDLE              FlashHandle,
+  IN  EFI_LBA                 Lba,
+  OUT CHAR16                  *UnicodeSN
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_BLOCK_IO_PROTOCOL       *BlockIoProtocol;
+  VOID                        *DataPtr;
+  BOOLEAN                     Found = FALSE;
+  UINT32                      Seed;
+  RANDOM_SERIAL_NUMBER        *RandomSN;
+  UINTN                       NumPages;
+  CHAR16                      UnicodeStr[SERIAL_NUMBER_SIZE];
+
+  if (UnicodeSN == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  Status = gBS->OpenProtocol (
+                  FlashHandle,
+                  &gEfiBlockIoProtocolGuid,
+                  (VOID **) &BlockIoProtocol,
+                  gImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_WARN,
+      "Warning: Couldn't open block device (status: %r)\n",
+      Status
+      ));
+    return EFI_DEVICE_ERROR;
+  }
+
+  NumPages = EFI_SIZE_TO_PAGES (BlockIoProtocol->Media->BlockSize);
+  DataPtr = AllocatePages (NumPages);
+  if (DataPtr == NULL) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+  Status = BlockIoProtocol->ReadBlocks (
+                              BlockIoProtocol,
+                              BlockIoProtocol->Media->MediaId,
+                              Lba,
+                              BlockIoProtocol->Media->BlockSize,
+                              DataPtr
+                              );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "Warning: Failed on reading blocks\n"));
+    goto Exit;
+  }
+
+  Seed = ArmGenericTimerGetSystemCount ();
+  RandomSN = (RANDOM_SERIAL_NUMBER *)DataPtr;
+  if (RandomSN->Magic == RANDOM_MAGIC) {
+    Found = TRUE;
+    //
+    // Verify the unicode string.
+    //
+    ZeroMem (UnicodeStr, SERIAL_NUMBER_SIZE * sizeof (CHAR16));
+    UnicodeSPrint (
+      UnicodeStr,
+      SERIAL_NUMBER_SIZE * sizeof (CHAR16),
+      L"%lx",
+      RandomSN->Data
+      );
+    if (StrLen (RandomSN->UnicodeSN) != StrLen (UnicodeStr)) {
+      Found = FALSE;
+    }
+    if (StrnCmp (RandomSN->UnicodeSN, UnicodeStr, StrLen (UnicodeStr)) != 0) {
+      Found = FALSE;
+    }
+  }
+  if (Found == FALSE) {
+    Status = GenerateUsbSNBySeed (Seed, RandomSN);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN, "Warning: Failed to generate serial number\n"));
+      goto Exit;
+    }
+    //
+    // Update SN to block device
+    //
+    Status = BlockIoProtocol->WriteBlocks (
+                                BlockIoProtocol,
+                                BlockIoProtocol->Media->MediaId,
+                                Lba,
+                                BlockIoProtocol->Media->BlockSize,
+                                DataPtr
+                                );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN, "Warning: Failed on writing blocks\n"));
+      goto Exit;
+    }
+  }
+  CopyMem (
+    UnicodeSN,
+    RandomSN->UnicodeSN,
+    SERIAL_NUMBER_SIZE * sizeof (CHAR16)
+    );
+Exit:
+  FreePages (DataPtr, NumPages);
+  return Status;
+}
+
+EFI_STATUS
+StoreSNToBlock (
+  IN EFI_HANDLE               FlashHandle,
+  IN EFI_LBA                  Lba,
+  IN CHAR16                   *UnicodeSN
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_BLOCK_IO_PROTOCOL       *BlockIoProtocol;
+  VOID                        *DataPtr;
+  UINTN                       NumPages;
+  RANDOM_SERIAL_NUMBER        *RandomSN;
+  CHAR16                      UnicodeStr[SERIAL_NUMBER_SIZE];
+
+  if (UnicodeSN == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  Status = gBS->OpenProtocol (
+                  FlashHandle,
+                  &gEfiBlockIoProtocolGuid,
+                  (VOID **) &BlockIoProtocol,
+                  gImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_WARN,
+      "Warning: Couldn't open block device (status: %r)\n",
+      Status
+      ));
+    return EFI_DEVICE_ERROR;
+  }
+  NumPages = EFI_SIZE_TO_PAGES (BlockIoProtocol->Media->BlockSize);
+  DataPtr = AllocatePages (NumPages);
+  if (DataPtr == NULL) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+  ZeroMem (DataPtr, BlockIoProtocol->Media->BlockSize);
+  RandomSN = (RANDOM_SERIAL_NUMBER *)DataPtr;
+  RandomSN->Magic = RANDOM_MAGIC;
+  StrnCpyS (
+    RandomSN->UnicodeSN,
+    SERIAL_NUMBER_SIZE * sizeof (CHAR16),
+    UnicodeSN,
+    StrSize (UnicodeSN)
+    );
+  RandomSN->Data = StrHexToUint64 (RandomSN->UnicodeSN);
+
+  //
+  // Verify the unicode string.
+  //
+  ZeroMem (UnicodeStr, SERIAL_NUMBER_SIZE * sizeof (CHAR16));
+  UnicodeSPrint (
+    UnicodeStr,
+    SERIAL_NUMBER_SIZE * sizeof (CHAR16),
+    L"%lx",
+    RandomSN->Data
+    );
+  if (StrLen (RandomSN->UnicodeSN) != StrLen (UnicodeStr)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (StrnCmp (RandomSN->UnicodeSN, UnicodeStr, StrLen (UnicodeStr)) != 0) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  Status = BlockIoProtocol->WriteBlocks (
+                              BlockIoProtocol,
+                              BlockIoProtocol->Media->MediaId,
+                              Lba,
+                              BlockIoProtocol->Media->BlockSize,
+                              DataPtr
+                              );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "Warning: Failed on writing blocks\n"));
+    goto Exit;
+  }
+Exit:
+  FreePages (DataPtr, NumPages);
+  return Status;
+}
