Library/UsbSerialNumberLib: assign usb serialno

Add the function to set specified usb serialno.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
diff --git a/Include/Library/UsbSerialNumberLib.h b/Include/Library/UsbSerialNumberLib.h
index 3ae594b..0ab4cc7 100644
--- a/Include/Library/UsbSerialNumberLib.h
+++ b/Include/Library/UsbSerialNumberLib.h
@@ -37,6 +37,12 @@
   );
 
 EFI_STATUS
+AssignUsbSN (
+  IN  CHAR8                  *AsciiCmd,
+  OUT CHAR16                 *UnicodeSN
+  );
+
+EFI_STATUS
 LoadSNFromBlock (
   IN  EFI_HANDLE              FlashHandle,
   IN  EFI_LBA                 Lba,
diff --git a/Library/UsbSerialNumberLib/UsbSerialNumberLib.c b/Library/UsbSerialNumberLib/UsbSerialNumberLib.c
index 2727d5c..550a973 100644
--- a/Library/UsbSerialNumberLib/UsbSerialNumberLib.c
+++ b/Library/UsbSerialNumberLib/UsbSerialNumberLib.c
@@ -28,6 +28,7 @@
 #include <Protocol/DevicePath.h>
 
 
+#define SERIAL_NUMBER_LEN                16
 #define SERIAL_NUMBER_SIZE               17
 
 #define RANDOM_MAX                       0x7FFFFFFFFFFFFFFF
@@ -105,6 +106,41 @@
 }
 
 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,
@@ -207,6 +243,7 @@
   CHAR16                      UnicodeStr[SERIAL_NUMBER_SIZE];
 
   if (UnicodeSN == NULL) {
+DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
     return EFI_INVALID_PARAMETER;
   }
   Status = gBS->OpenProtocol (
@@ -236,10 +273,12 @@
   ZeroMem (UnicodeStr, SERIAL_NUMBER_SIZE * sizeof (CHAR16));
   UnicodeSPrint (UnicodeStr, SERIAL_NUMBER_SIZE * sizeof (CHAR16), L"%lx", RandomSN->Data);
   if (StrLen (RandomSN->UnicodeSN) != StrLen (UnicodeStr)) {
+DEBUG ((DEBUG_ERROR, "#%a, %d, strlen:%d, %d\n", __func__, __LINE__, StrLen (RandomSN->UnicodeSN), StrLen (UnicodeStr)));
     Status = EFI_INVALID_PARAMETER;
     goto Exit;
   }
   if (StrnCmp (RandomSN->UnicodeSN, UnicodeStr, StrLen (UnicodeStr)) != 0) {
+DEBUG ((DEBUG_ERROR, "#%a, %d, %s, %s\n", __func__, __LINE__, RandomSN->UnicodeSN, UnicodeStr));
     Status = EFI_INVALID_PARAMETER;
     goto Exit;
   }