[edk2,edk-platforms,v1,1/4] Platform/Hisilicon: add UsbSerialNumberLib

Message ID 1534761109-27037-2-git-send-email-haojian.zhuang@linaro.org
State New
Headers show
Series
  • enable USB on HiKey960
Related show

Commit Message

Haojian Zhuang Aug. 20, 2018, 10:31 a.m.
Add UsbSerialNumberLib. The Library could generate USB Serial Number
that is used in USB device driver. And it could load/save the USB
Serial Number into storage device.

Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

---
 Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.dec               |  32 ++
 Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.inf               |  45 +++
 Platform/Hisilicon/Library/UsbSerialNumberLib/Include/Library/UsbSerialNumberLib.h |  59 ++++
 Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.c                 | 341 ++++++++++++++++++++
 4 files changed, 477 insertions(+)

-- 
2.7.4

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Comments

Leif Lindholm Oct. 4, 2018, 4:48 p.m. | #1
Ah, here's UsbSerialNumberLib. Got it.
(Please mention dependencies on other patchsets in the cover-letter.)

Please wrap these 3 sets together into a single one, with patches in
dependency order, for v2.

I will comment on this patch aftes I'm done with DwUsb2.

/
    Leif

On Mon, Aug 20, 2018 at 06:31:46PM +0800, Haojian Zhuang wrote:
> Add UsbSerialNumberLib. The Library could generate USB Serial Number

> that is used in USB device driver. And it could load/save the USB

> Serial Number into storage device.

> 

> Cc: Leif Lindholm <leif.lindholm@linaro.org>

> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> Contributed-under: TianoCore Contribution Agreement 1.1

> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

> ---

>  Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.dec               |  32 ++

>  Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.inf               |  45 +++

>  Platform/Hisilicon/Library/UsbSerialNumberLib/Include/Library/UsbSerialNumberLib.h |  59 ++++

>  Platform/Hisilicon/Library/UsbSerialNumberLib/UsbSerialNumberLib.c                 | 341 ++++++++++++++++++++

>  4 files changed, 477 insertions(+)

> 

> 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;

> +}

> -- 

> 2.7.4

> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Patch

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;
+}