]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPlatformPkg/ArmJunoDxe: Add PCI GBE MAC address to Juno R1 boot options
authorRonald Cron <ronald.cron@arm.com>
Wed, 1 Apr 2015 14:46:52 +0000 (14:46 +0000)
committeroliviermartin <oliviermartin@Edk2>
Wed, 1 Apr 2015 14:46:52 +0000 (14:46 +0000)
On Juno R1, the MAC address assigned to the PCI Gigabyte Ethernet device
as to be passed to the Linux Kernel.

The MAC address is passed to the Linux Kernel by means of the boot argument
"sky2.mac_address".

This patch adds this boot argument to the lists of boot arguments of the
two Juno R1 default boot options.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17095 6f19259b-4bc3-4df7-8a09-765794883524

ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c
ArmPlatformPkg/ArmJunoPkg/Include/ArmPlatform.h

index e94047ab8b3fbbcaaaaebe2c70c2003baae7c6a0..fe21f637313345cf131e380f4c9779ab1c3c7b5a 100644 (file)
@@ -13,6 +13,7 @@
 **/\r
 \r
 #include "ArmJunoDxeInternal.h"\r
+#include <ArmPlatform.h>\r
 \r
 #include <Protocol/DevicePathFromText.h>\r
 \r
 #include <Library/DevicePathLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PrintLib.h>\r
+\r
+//\r
+// Size in number of characters of the Linux boot argument\r
+// passing the MAC address to be used by the PCI GigaByte\r
+// Ethernet device : " sky2.mac_address=0x11,0x22,0x33,0x44,0x55,0x66"\r
+//\r
+#define SKY2_MAC_ADDRESS_BOOTARG_LEN  47\r
+\r
+//\r
+// Hardware platform identifiers\r
+//\r
+typedef enum {\r
+  UNKNOWN,\r
+  JUNO_R0,\r
+  JUNO_R1\r
+} JUNO_REVISION;\r
+\r
+//\r
+// Function prototypes\r
+//\r
+STATIC EFI_STATUS SetJunoR1DefaultBootEntries (\r
+  VOID\r
+  );\r
 \r
 // This GUID must match the FILE_GUID in ArmPlatformPkg/ArmJunoPkg/AcpiTables/AcpiTables.inf\r
 STATIC CONST EFI_GUID mJunoAcpiTableFile = { 0xa1dd808e, 0x1e95, 0x4399, { 0xab, 0xc0, 0x65, 0x3c, 0x82, 0xe8, 0x53, 0x0c } };\r
@@ -112,8 +138,9 @@ ArmJunoEntryPoint (
   UINT32                Midr;\r
   UINT32                CpuType;\r
   UINT32                CpuRev;\r
-  BOOLEAN               IsJunoR1;\r
+  JUNO_REVISION         JunoRevision;\r
 \r
+  JunoRevision = UNKNOWN;\r
   Status = PciEmulationEntryPoint ();\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -163,36 +190,58 @@ ArmJunoEntryPoint (
   }\r
 \r
   //\r
-  // Set up the device path to the FDT.\r
   // We detect whether we are running on a Juno r0 or Juno r1 board at\r
   // runtime by checking the value of the MIDR register.\r
   //\r
 \r
-  Midr           = ArmReadMidr ();\r
-  CpuType        = (Midr >> ARM_CPU_TYPE_SHIFT) & ARM_CPU_TYPE_MASK;\r
-  CpuRev         = Midr & ARM_CPU_REV_MASK;\r
-  TextDevicePath = NULL;\r
-  IsJunoR1       = FALSE;\r
+  Midr     = ArmReadMidr ();\r
+  CpuType  = (Midr >> ARM_CPU_TYPE_SHIFT) & ARM_CPU_TYPE_MASK;\r
+  CpuRev   = Midr & ARM_CPU_REV_MASK;\r
 \r
   switch (CpuType) {\r
   case ARM_CPU_TYPE_A53:\r
     if (CpuRev == ARM_CPU_REV (0, 0)) {\r
-      TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoR0FdtDevicePath);\r
+      JunoRevision = JUNO_R0;\r
     } else if (CpuRev == ARM_CPU_REV (0, 3)) {\r
-      TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoR1A57x2FdtDevicePath);\r
-      IsJunoR1       = TRUE;\r
+      JunoRevision = JUNO_R1;\r
     }\r
     break;\r
 \r
   case ARM_CPU_TYPE_A57:\r
     if (CpuRev == ARM_CPU_REV (0, 0)) {\r
-      TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoR0FdtDevicePath);\r
+      JunoRevision = JUNO_R0;\r
     } else if (CpuRev == ARM_CPU_REV (1, 1)) {\r
-      TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoR1A57x2FdtDevicePath);\r
-      IsJunoR1       = TRUE;\r
+      JunoRevision = JUNO_R1;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Set the R1 two boot options if not already done.\r
+  //\r
+\r
+  if (JunoRevision == JUNO_R1) {\r
+    Status = SetJunoR1DefaultBootEntries ();\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
     }\r
   }\r
 \r
+  //\r
+  // Set up the device path to the FDT.\r
+  //\r
+  switch (JunoRevision) {\r
+  case JUNO_R0:\r
+    TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoR0FdtDevicePath);\r
+    break;\r
+\r
+  case JUNO_R1:\r
+    TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoR1A57x2FdtDevicePath);\r
+    break;\r
+\r
+  default:\r
+    TextDevicePath = NULL;\r
+  }\r
+\r
   if (TextDevicePath != NULL) {\r
     TextDevicePathSize = StrSize (TextDevicePath);\r
     Buffer = PcdSetPtr (PcdFdtDevicePaths, &TextDevicePathSize, TextDevicePath);\r
@@ -212,77 +261,171 @@ ArmJunoEntryPoint (
   // Try to install the ACPI Tables\r
   Status = LocateAndInstallAcpiFromFv (&mJunoAcpiTableFile);\r
 \r
+  return Status;\r
+}\r
+\r
+/**\r
+ * If no boot entry is currently defined, define the two default boot entries\r
+ * for Juno R1.\r
+ *\r
+ * @return EFI_SUCCESS             Some boot entries were already defined or\r
+ *                                 the default boot entries were set successfully.\r
+ * @return EFI_OUT_OF_RESOURCES    A memory allocation failed.\r
+ * @return EFI_DEVICE_ERROR        An UEFI variable could not be saved due to a hardware failure.\r
+ * @return EFI_WRITE_PROTECTED     An UEFI variable is read-only.\r
+ * @return EFI_SECURITY_VIOLATION  An UEFI variable could not be written.\r
+ */\r
+STATIC\r
+EFI_STATUS\r
+SetJunoR1DefaultBootEntries (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  CONST CHAR16*                       ExtraBootArgument = L" dtb=juno-r1-ca57x2_ca53x4.dtb";\r
+  UINTN                               Size;\r
+  EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL  *EfiDevicePathFromTextProtocol;\r
+  EFI_DEVICE_PATH*                    BootDevicePath;\r
+  UINT32                              SysPciGbeL;\r
+  UINT32                              SysPciGbeH;\r
+  CHAR16*                             DefaultBootArgument;\r
+  CHAR16*                             DefaultBootArgument1;\r
+  UINTN                               DefaultBootArgument1Size;\r
+  CHAR16*                             DefaultBootArgument2;\r
+  UINTN                               DefaultBootArgument2Size;\r
+  UINT16                              BootOrder[2];\r
+\r
+  BootDevicePath       = NULL;\r
+  DefaultBootArgument1 = NULL;\r
+  DefaultBootArgument2 = NULL;\r
+\r
   //\r
-  // If Juno R1 and it is the first boot then default boot entries will be created\r
+  // Because the driver has a dependency on gEfiVariable(Write)ArchProtocolGuid\r
+  // (see [Depex] section of the INF file), we know we can safely access the\r
+  // UEFI Variable at that stage.\r
   //\r
-  if (IsJunoR1) {\r
-    CONST CHAR16*                       ExtraBootArgument = L" dtb=juno-r1-ca57x2_ca53x4.dtb";\r
-    UINTN                               Size;\r
-    EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol;\r
-    EFI_DEVICE_PATH*                    BootDevicePath;\r
-    CHAR16*                             DefaultBootArgument;\r
-    UINTN                               DefaultBootArgumentSize;\r
-    CHAR16*                             DefaultBootArgument2;\r
-    UINTN                               DefaultBootArgument2Size;\r
-    UINT16                              BootOrder[2];\r
-\r
-    // Because the driver has a dependency on gEfiVariable(Write)ArchProtocolGuid (see [Depex]\r
-    // section of the INF file), we know we can safely access the UEFI Variable at that stage.\r
-    Size = 0;\r
-    Status = gRT->GetVariable (L"BootOrder", &gEfiGlobalVariableGuid, NULL, &Size, NULL);\r
-    if (Status == EFI_NOT_FOUND) {\r
-      Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);\r
-      if (EFI_ERROR (Status)) {\r
-        // You must provide an implementation of DevicePathFromTextProtocol in your firmware (eg: DevicePathDxe)\r
-        DEBUG ((EFI_D_ERROR, "Error: Require DevicePathFromTextProtocol\n"));\r
-        return Status;\r
-      }\r
-      // We use the same default kernel\r
-      BootDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath));\r
-\r
-      // Create the entry if the Default values are correct\r
-      if (BootDevicePath != NULL) {\r
-        DefaultBootArgument = (CHAR16*)PcdGetPtr (PcdDefaultBootArgument);\r
-        DefaultBootArgumentSize = StrSize (DefaultBootArgument);\r
-        DefaultBootArgument2Size = DefaultBootArgumentSize + StrSize (ExtraBootArgument);\r
-\r
-        DefaultBootArgument2 = AllocatePool (DefaultBootArgument2Size);\r
-        if (DefaultBootArgument2 == NULL) {\r
-          FreePool (BootDevicePath);\r
-          return EFI_OUT_OF_RESOURCES;\r
-        }\r
-        CopyMem (DefaultBootArgument2, DefaultBootArgument, DefaultBootArgumentSize);\r
-        CopyMem ((UINT8*)DefaultBootArgument2 + (StrLen (DefaultBootArgument2) * sizeof (CHAR16)), ExtraBootArgument, StrSize (ExtraBootArgument));\r
-\r
-        // Create Boot0001 environment variable\r
-        Status = BootOptionCreate (L"Boot0001", LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT,\r
-            L"Linux with A57x2", BootDevicePath,\r
-            (UINT8*)DefaultBootArgument, DefaultBootArgumentSize);\r
-        ASSERT_EFI_ERROR (Status);\r
-\r
-        // Create Boot0002 environment variable\r
-        Status = BootOptionCreate (L"Boot0002", LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT,\r
-            L"Linux with A57x2_A53x4", BootDevicePath,\r
-            (UINT8*)DefaultBootArgument2, DefaultBootArgument2Size);\r
-        ASSERT_EFI_ERROR (Status);\r
-\r
-        // Add the new Boot Index to the list\r
-        BootOrder[0] = 1; // Boot0001\r
-        BootOrder[1] = 2; // Boot0002\r
-        Status = gRT->SetVariable (\r
-            L"BootOrder",\r
-            &gEfiGlobalVariableGuid,\r
-            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
-            sizeof (BootOrder),\r
-            BootOrder\r
-            );\r
-\r
-        FreePool (BootDevicePath);\r
-        FreePool (DefaultBootArgument2);\r
-      } else {\r
-        Status = EFI_UNSUPPORTED;\r
-      }\r
-    }\r
+  Size = 0;\r
+  Status = gRT->GetVariable (L"BootOrder", &gEfiGlobalVariableGuid, NULL, &Size, NULL);\r
+  if (Status != EFI_NOT_FOUND) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiDevicePathFromTextProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&EfiDevicePathFromTextProtocol\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // You must provide an implementation of DevicePathFromTextProtocol\r
+    // in your firmware (eg: DevicePathDxe)\r
+    //\r
+    DEBUG ((EFI_D_ERROR, "Error: Require DevicePathFromTextProtocol\n"));\r
+    return Status;\r
+  }\r
+  //\r
+  // We use the same default kernel.\r
+  //\r
+  BootDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (\r
+                     (CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath)\r
+                     );\r
+  if (BootDevicePath == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  DefaultBootArgument = (CHAR16*)PcdGetPtr (PcdDefaultBootArgument);\r
+  DefaultBootArgument1Size = StrSize (DefaultBootArgument) +\r
+                             (SKY2_MAC_ADDRESS_BOOTARG_LEN * sizeof (CHAR16));\r
+  DefaultBootArgument2Size = DefaultBootArgument1Size + StrSize (ExtraBootArgument);\r
+\r
+  Status = EFI_OUT_OF_RESOURCES;\r
+  DefaultBootArgument1 = AllocatePool (DefaultBootArgument1Size);\r
+  if (DefaultBootArgument1 == NULL) {\r
+    goto Error;\r
+  }\r
+  DefaultBootArgument2 = AllocatePool (DefaultBootArgument2Size);\r
+  if (DefaultBootArgument2 == NULL) {\r
+    goto Error;\r
+  }\r
+\r
+  SysPciGbeL = MmioRead32 (ARM_JUNO_SYS_PCIGBE_L);\r
+  SysPciGbeH = MmioRead32 (ARM_JUNO_SYS_PCIGBE_H);\r
+\r
+  UnicodeSPrint (\r
+    DefaultBootArgument1,\r
+    DefaultBootArgument1Size,\r
+    L"%s sky2.mac_address=0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x",\r
+    DefaultBootArgument,\r
+    (SysPciGbeH >> 8 ) & 0xFF, (SysPciGbeH      ) & 0xFF,\r
+    (SysPciGbeL >> 24) & 0xFF, (SysPciGbeL >> 16) & 0xFF,\r
+    (SysPciGbeL >> 8 ) & 0xFF, (SysPciGbeL      ) & 0xFF\r
+    );\r
+\r
+  CopyMem (DefaultBootArgument2, DefaultBootArgument1, DefaultBootArgument1Size);\r
+  CopyMem (\r
+    (UINT8*)DefaultBootArgument2 + DefaultBootArgument1Size - sizeof (CHAR16),\r
+    ExtraBootArgument,\r
+    StrSize (ExtraBootArgument)\r
+  );\r
+\r
+  //\r
+  // Create Boot0001 environment variable\r
+  //\r
+  Status = BootOptionCreate (\r
+             L"Boot0001", LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT,\r
+             L"Linux with A57x2", BootDevicePath,\r
+             (UINT8*)DefaultBootArgument1, DefaultBootArgument1Size\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (TRUE);\r
+    goto Error;\r
+  }\r
+\r
+  //\r
+  // Create Boot0002 environment variable\r
+  //\r
+  Status = BootOptionCreate (\r
+             L"Boot0002", LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT,\r
+             L"Linux with A57x2_A53x4", BootDevicePath,\r
+             (UINT8*)DefaultBootArgument2, DefaultBootArgument2Size\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (TRUE);\r
+    goto Error;\r
+  }\r
+\r
+  //\r
+  // Add the new Boot Index to the list\r
+  //\r
+  BootOrder[0] = 1; // Boot0001\r
+  BootOrder[1] = 2; // Boot0002\r
+  Status = gRT->SetVariable (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE       |\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS |\r
+                  EFI_VARIABLE_RUNTIME_ACCESS,\r
+                  sizeof (BootOrder),\r
+                  BootOrder\r
+                  );\r
+\r
+  Error:\r
+  if (BootDevicePath != NULL) {\r
+    FreePool (BootDevicePath);\r
+  }\r
+  if (DefaultBootArgument1 != NULL) {\r
+    FreePool (DefaultBootArgument1);\r
+  }\r
+  if (DefaultBootArgument2 != NULL) {\r
+    FreePool (DefaultBootArgument2);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      EFI_D_ERROR,\r
+      "ArmJunoDxe - The setting of the default boot entries failed - %r\n",\r
+      Status\r
+      ));\r
   }\r
 \r
   return Status;\r
index badd7a64fb5459eb6b7c6f936967415bb2767c03..c0a2b71484fc75e8564e40093a64df639ebc81f7 100644 (file)
 // Define if the exported ACPI Tables are based on ACPI 5.0 spec or latest\r
 //#define ARM_JUNO_ACPI_5_0\r
 \r
+//\r
+// Address of the system registers that contain the MAC address\r
+// assigned to the PCI Gigabyte Ethernet device.\r
+//\r
+\r
+#define ARM_JUNO_SYS_PCIGBE_L  (ARM_VE_BOARD_PERIPH_BASE + 0x74)\r
+#define ARM_JUNO_SYS_PCIGBE_H  (ARM_VE_BOARD_PERIPH_BASE + 0x78)\r
+\r
 #endif\r