ArmPlatformPkg/ArmJunoDxe: Add PCI GBE MAC address to Juno R1 boot options

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
This commit is contained in:
Ronald Cron
2015-04-01 14:46:52 +00:00
committed by oliviermartin
parent 58bc40654e
commit c1fee786c1
2 changed files with 226 additions and 75 deletions

View File

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

View File

@@ -80,4 +80,12 @@
// Define if the exported ACPI Tables are based on ACPI 5.0 spec or latest // Define if the exported ACPI Tables are based on ACPI 5.0 spec or latest
//#define ARM_JUNO_ACPI_5_0 //#define ARM_JUNO_ACPI_5_0
//
// Address of the system registers that contain the MAC address
// assigned to the PCI Gigabyte Ethernet device.
//
#define ARM_JUNO_SYS_PCIGBE_L (ARM_VE_BOARD_PERIPH_BASE + 0x74)
#define ARM_JUNO_SYS_PCIGBE_H (ARM_VE_BOARD_PERIPH_BASE + 0x78)
#endif #endif