diff mbox series

[edk2,edk2-platforms,v1,22/38] Platform/Hisilicon/D06: Add OemNicLib

Message ID 20180724070922.63362-23-ming.huang@linaro.org
State New
Headers show
Series Upload for D06 platform | expand

Commit Message

Ming Huang July 24, 2018, 7:09 a.m. UTC
OemNicLib provide nic related api like GetMac,SetMac.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ming Huang <ming.huang@linaro.org>

Signed-off-by: Heyi Guo <heyi.guo@linaro.org>

---
 Platform/Hisilicon/D06/D06.dsc                         |   1 +
 Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c   | 571 ++++++++++++++++++++
 Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf |  35 ++
 3 files changed, 607 insertions(+)

-- 
2.17.0

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

Comments

Leif Lindholm Aug. 3, 2018, 2:36 p.m. UTC | #1
On Tue, Jul 24, 2018 at 03:09:06PM +0800, Ming Huang wrote:
> OemNicLib provide nic related api like GetMac,SetMac.

> 

> Contributed-under: TianoCore Contribution Agreement 1.1

> Signed-off-by: Ming Huang <ming.huang@linaro.org>

> Signed-off-by: Heyi Guo <heyi.guo@linaro.org>

> ---

>  Platform/Hisilicon/D06/D06.dsc                         |   1 +

>  Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c   | 571 ++++++++++++++++++++

>  Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf |  35 ++

>  3 files changed, 607 insertions(+)

> 

> diff --git a/Platform/Hisilicon/D06/D06.dsc b/Platform/Hisilicon/D06/D06.dsc

> index 43af043cfd..744a4a0d6d 100644

> --- a/Platform/Hisilicon/D06/D06.dsc

> +++ b/Platform/Hisilicon/D06/D06.dsc

> @@ -91,6 +91,7 @@

>  

>    LpcLib|Silicon/Hisilicon/Hi1620/Library/LpcLibHi1620/LpcLib.inf

>    SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf

> +  OemNicLib|Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf

>  !if $(SECURE_BOOT_ENABLE) == TRUE

>    FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf

>  !endif

> diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c

> new file mode 100644

> index 0000000000..55ed1625ce

> --- /dev/null

> +++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c

> @@ -0,0 +1,571 @@

> +/** @file

> +*

> +*  Copyright (c) 2018, Hisilicon Limited. All rights reserved.

> +*  Copyright (c) 2017, 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.

> +*

> +**/

> +

> +#include <Uefi.h>

> +#include <Library/CpldIoLib.h>

> +#include <Library/DebugLib.h>

> +#include <Library/I2CLib.h>

> +#include <Library/IoLib.h>

> +#include <Library/OemNicLib.h>

> +

> +#define CPU2_SFP2_100G_CARD_OFFSET   0x25

> +#define CPU1_SFP1_LOCATE_OFFSET      0x16

> +#define CPU1_SFP0_LOCATE_OFFSET      0x12

> +#define CPU2_SFP1_LOCATE_OFFSET      0x21

> +#define CPU2_SFP0_LOCATE_OFFSET      0x19

> +#define CPU2_SFP2_10G_GE_CARD_OFFSET 0x25

> +

> +#define SFP_10G_SPEED   10

> +#define SFP_25G_SPEED   25

> +#define SFP_100G_SPEED  100

> +#define SFP_GE_SPEED    1

> +

> +#define SFP_GE_SPEED_VAL_VENDOR_FINISAR 0x0C

> +#define SFP_GE_SPEED_VAL                0x0D

> +#define SFP_10G_SPEED_VAL               0x67

> +#define SFP_25G_SPEED_VAL               0xFF

> +

> +#define CPU1_9545_I2C_ADDR 0x70

> +#define CPU2_9545_I2C_ADDR 0x71

> +

> +#define FIBER_PRESENT     0

> +#define CARD_PRESENT      1

> +#define I2C_PORT_SFP      4

> +#define CPU2_I2C_PORT_SFP 5

> +

> +#define SOCKET_0                 0

> +#define SOCKET_1                 1

> +#define EEPROM_I2C_PORT          4

> +#define EEPROM_PAGE_SIZE         0x40

> +#define MAC_ADDR_LEN             6

> +#define I2C_OFFSET_EEPROM_ETH0   (0xc00)

> +#define I2C_SLAVEADDR_EEPROM     (0x52)

> +

> +#pragma pack(1)

> +typedef struct {

> +  UINT16 Crc16;

> +  UINT16 MacLen;

> +  UINT8  Mac[MAC_ADDR_LEN];

> +} NIC_MAC_ADDRESS;

> +#pragma pack()

> +

> +ETH_PRODUCT_DESC gEthPdtDesc[ETH_MAX_PORT] =

> +{

> +    {TRUE,   ETH_SPEED_10KM,  ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID},

> +    {TRUE,   ETH_SPEED_10KM,  ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID},

> +    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID},

> +    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID},

> +    {TRUE,   ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 0},

> +    {TRUE,   ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 1},

> +    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID},

> +    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID}

> +};

> +

> +volatile unsigned char g_2pserveraddr[4][6] = {


VOLATILE UINT8.
No '_' in variable name.
Also, can we please have #defines for that 4 and 6?

> +  {0x00, 0x18, 0x16, 0x29, 0x11, 0x00},

> +  {0x00, 0x18, 0x16, 0x29, 0x11, 0x01},

> +  {0x00, 0x18, 0x16, 0x29, 0x11, 0x02},

> +  {0x00, 0x18, 0x16, 0x29, 0x11, 0x03}

> +};

> +

> +UINT16 crc_tab[256] = {


CrcTable.
Hmm.
This might be useful to add to a core library/driver/protocol. We
don't appear to have it yet. This is another note to the universe.

> +  0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,

> +  0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,

> +  0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,

> +  0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,

> +  0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,

> +  0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,

> +  0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,

> +  0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,

> +  0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,

> +  0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,

> +  0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,

> +  0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,

> +  0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,

> +  0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,

> +  0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,

> +  0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,

> +  0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,

> +  0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,

> +  0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,

> +  0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,

> +  0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,

> +  0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,

> +  0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,

> +  0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,

> +  0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,

> +  0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,

> +  0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,

> +  0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,

> +  0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,

> +  0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,

> +  0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,

> +  0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0,

> +};

> +

> +EFI_STATUS

> +GetSfpSpeed (

> +  UINT16 Socket,

> +  UINT16 SfpNum,

> +  UINT8* FiberSpeed

> +  )

> +{

> +  EFI_STATUS  Status;

> +  I2C_DEVICE  SpdDev;

> +  UINT8       SpdReg;

> +  UINT8       SfpSpeed;

> +  UINT32      RegAddr;

> +  UINT16      I2cAddr;

> +  UINT32      SfpPort;

> +

> +  SfpSpeed = 0x0;

> +  if(Socket == 1) {


Space before '('.
Please add a descriptive #define for that 1.

> +    I2cAddr =  CPU2_9545_I2C_ADDR;

> +    SfpPort = CPU2_I2C_PORT_SFP;

> +  } else {

> +    I2cAddr =  CPU1_9545_I2C_ADDR;

> +    SfpPort = I2C_PORT_SFP;

> +  }

> +

> +  Status = I2CInit (Socket, SfpPort, Normal);

> +  if (EFI_ERROR (Status))

> +  {

> +      DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Socket%d Call I2CInit failed! p1=0x%x.\n",

> +             __FUNCTION__, __LINE__, Socket, Status));

> +      return Status;

> +  }

> +

> +  SpdDev.Socket = Socket;

> +  SpdDev.DeviceType         =  DEVICE_TYPE_SPD;

> +  SpdDev.Port               =  SfpPort;

> +  SpdDev.SlaveDeviceAddress =  I2cAddr;

> +  RegAddr                   =  0x0;

> +  SpdReg                    =  1 << (SfpNum - 1);


Please add descriptive #define.

> +

> +  Status = I2CWrite (&SpdDev, RegAddr, 1, &SpdReg);

> +  if (EFI_ERROR (Status)) {

> +      DEBUG ((DEBUG_ERROR, "I2CWrite Error =%r.\n", Status));

> +      return Status;

> +  }

> +

> +  SpdDev.Socket = Socket;

> +  SpdDev.DeviceType         =  DEVICE_TYPE_SPD;

> +  SpdDev.Port               =  SfpPort;

> +  SpdDev.SlaveDeviceAddress =  0x50;


Please add descriptive #define.

> +

> +  RegAddr                   =  12;


Please add descriptive #define.

> +  Status = I2CRead (&SpdDev, RegAddr, 1, &SfpSpeed);

> +  if (EFI_ERROR (Status)) {

> +      DEBUG ((DEBUG_ERROR, "I2CRead Error =%r.\n", Status));

> +      return Status;

> +  }

> +

> +  DEBUG ((DEBUG_INFO, "BR, Nominal, Nominal signalling rate, SfpSpeed:    0x%x\n",

> +         SfpSpeed));

> +

> +  if (SfpSpeed == SFP_10G_SPEED_VAL) {

> +    *FiberSpeed = SFP_10G_SPEED;

> +  } else if (SfpSpeed == SFP_25G_SPEED_VAL) {

> +    *FiberSpeed = SFP_25G_SPEED;

> +  } else if ((SfpSpeed == SFP_GE_SPEED_VAL) || (SfpSpeed == SFP_GE_SPEED_VAL_VENDOR_FINISAR)) {


Long line, please break.

> +    *FiberSpeed = SFP_GE_SPEED;

> +  }

> +

> +  return EFI_SUCCESS;

> +}

> +

> +//Fiber1Type/Fiber2Type/Fiber3Type return: SFP_10G_SPEED, SFP_100G_SPEED, SFP_GE_SPEED

> +UINT32

> +GetCpu2FiberType (

> +  UINT8* Fiber1Type,

> +  UINT8* Fiber2Type,

> +  UINT8* Fiber100Ge

> +  )

> +{

> +  EFI_STATUS  Status;

> +  UINT16      SfpNum1;

> +  UINT8       SfpSpeed1;

> +  UINT16      SfpNum2;

> +  UINT8       SfpSpeed2;

> +

> +  SfpNum1 = 0x1;

> +  SfpSpeed1 = SFP_10G_SPEED;

> +  SfpNum2 = 0x2;

> +  SfpSpeed2 = SFP_10G_SPEED;

> +  *Fiber100Ge = 0x0;

> +  *Fiber1Type = SFP_10G_SPEED;

> +  *Fiber2Type = SFP_10G_SPEED;

> +

> +  if ((ReadCpldReg (CPU2_SFP2_100G_CARD_OFFSET) & BIT7) == (CARD_PRESENT << 7)) {


Please add descriptively named helper macros or #defines (& BIT7, << 7).

> +    // 100 Ge card

> +    *Fiber1Type = SFP_10G_SPEED;

> +    *Fiber2Type = SFP_10G_SPEED;

> +    *Fiber100Ge = SFP_100G_SPEED;

> +    DEBUG ((DEBUG_ERROR,"Detect Fiber SFP_100G is Present, Set 100Ge\n"));

> +  } else if ((ReadCpldReg (CPU2_SFP2_10G_GE_CARD_OFFSET) & BIT0) == CARD_PRESENT) {


Please add descriptively named helper macro or #define (& BIT0).

> +    *Fiber100Ge = 0x0;

> +    *Fiber1Type = SFP_10G_SPEED;

> +    *Fiber2Type = SFP_10G_SPEED;

> +    if (ReadCpldReg (CPU2_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) {

> +      // Fiber detected in CPU2 slot0, read speed via i2c

> +      Status = GetSfpSpeed (SOCKET_1, SfpNum1, &SfpSpeed1);

> +      if (EFI_ERROR (Status)) {

> +        DEBUG((DEBUG_ERROR,

> +               "Get Socket1 Sfp%d Speed Error: %r.\n",

> +               SfpNum1,

> +               Status));

> +        return Status;

> +      }

> +      if (SfpSpeed1 == SFP_25G_SPEED) {

> +        // P1 don't support 25G, so set speed to 10G

> +        *Fiber1Type = SFP_10G_SPEED;

> +      } else {

> +        *Fiber1Type = SfpSpeed1;

> +      }

> +    } else {

> +      // No fiber, set speed to 10G

> +      *Fiber1Type = SFP_10G_SPEED;

> +    }

> +

> +    if (ReadCpldReg (CPU2_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) {

> +      // Fiber detected in CPU2 slot1, read speed via i2c

> +      Status = GetSfpSpeed (SOCKET_1, SfpNum2, &SfpSpeed2);

> +      if (EFI_ERROR (Status)) {

> +        DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status));

> +        return Status;

> +      }

> +      if (SfpSpeed2 == SFP_25G_SPEED) {

> +        *Fiber2Type = SFP_10G_SPEED;

> +      } else {

> +        *Fiber2Type = SfpSpeed2;

> +      }

> +    } else {

> +      // No fiber, set speed to 10G

> +      *Fiber2Type = SFP_10G_SPEED;

> +    }

> +  } else {

> +    // 100Ge/10Ge/Ge Fiber is not found.

> +    *Fiber1Type = SFP_10G_SPEED;

> +    *Fiber2Type = SFP_10G_SPEED;

> +    *Fiber100Ge = 0x0;

> +  }

> +

> +  return EFI_SUCCESS;

> +}

> +

> +//Fiber1Type/Fiber2Type return: SFP_10G_SPEED, SFP_25G_SPEED, SFP_GE_SPEED

> +UINT32

> +GetCpu1FiberType (

> +  UINT8* Fiber1Type,

> +  UINT8* Fiber2Type

> +  )

> +{

> +  EFI_STATUS  Status;

> +  UINT16      SfpNum1;

> +  UINT8       SfpSpeed1;

> +  UINT16      SfpNum2;

> +  UINT8       SfpSpeed2;

> +

> +  SfpNum1 = 0x1;

> +  SfpSpeed1 = SFP_10G_SPEED;

> +  SfpNum2 = 0x2;

> +  SfpSpeed2 = SFP_10G_SPEED;

> +  *Fiber1Type = SFP_10G_SPEED;

> +  *Fiber2Type = SFP_10G_SPEED;

> +  // Fiber detected in CPU1 slot0, read speed via i2c

> +  if (ReadCpldReg (CPU1_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) {

> +    Status = GetSfpSpeed (SOCKET_0, SfpNum1, &SfpSpeed1);

> +    if (EFI_ERROR (Status)) {

> +      DEBUG ((DEBUG_ERROR, "Get Socket0 Sfp%d Speed Error: %r.\n",

> +              SfpNum1, Status));

> +      return Status;

> +    }

> +    *Fiber1Type = SfpSpeed1;

> +  } else {

> +    *Fiber1Type = SFP_10G_SPEED;

> +  }

> +

> +  // Fiber detected in CPU1 slot1, read speed via i2c

> +  if (ReadCpldReg (CPU1_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) {

> +    Status = GetSfpSpeed (SOCKET_0, SfpNum2, &SfpSpeed2);

> +    if (EFI_ERROR (Status)) {

> +      *Fiber2Type = SFP_10G_SPEED;

> +      DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status));

> +      return Status;

> +    }

> +    *Fiber2Type = SfpSpeed2;

> +  } else {

> +    *Fiber2Type = SFP_10G_SPEED;

> +  }

> +

> +  return EFI_SUCCESS;

> +}

> +

> +UINT16 make_crc_checksum (


MakeCrcChecksum

> +  UINT8 *buf,


Buffer.

> +  UINT32 len


Length.

> +  )

> +{

> +  UINT16 StartCRC = 0;

> +

> +  if (len > (512 * 1024)) {


SIZE_512KB?

> +    return 0;

> +  }

> +

> +  if (buf == NULL) {

> +    return 0;

> +  }

> +

> +  while (len) {

> +    StartCRC = crc_tab [((UINT8) ((StartCRC >> 8) & 0xff)) ^ *(buf++)] ^

> +               ((UINT16) (StartCRC << 8));

> +    len--;

> +  }

> +

> +  return StartCRC;

> +}

> +

> +

> +EFI_STATUS

> +OemGetMacE2prom(

> +  IN  UINT32 Port,

> +  OUT UINT8  *pucAddr


Hungarian notation. Drop 'puc'.

> +  )

> +{

> +  I2C_DEVICE       stI2cDev = {0};


Hungarian notation. Drop 'st'.

> +  EFI_STATUS       Status;

> +  UINT16           I2cOffset;

> +  UINT16           crc16;


Crc16.

> +  NIC_MAC_ADDRESS  stMacDesc = {0};


Hungarian notation. Drop 'st'.

> +  UINT16           RemainderMacOffset;

> +  UINT16           LessSizeOfPage;

> +  UINT32           i = 0;


I.

> +

> +  Status = I2CInit (0, EEPROM_I2C_PORT, Normal);

> +  if (EFI_ERROR (Status))

> +  {

> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n",

> +            __FUNCTION__, __LINE__, Status));

> +    return Status;

> +  }

> +

> +  I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS));

> +

> +  stI2cDev.DeviceType = DEVICE_TYPE_E2PROM;

> +  stI2cDev.Port = EEPROM_I2C_PORT;

> +  stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM;

> +  stI2cDev.Socket = 0;

> +  RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE;

> +  LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset;

> +  //The length of NIC_MAC_ADDRESS is 10 bytes long,

> +  //It surly less than EEPROM page size, so we could

> +  //code as bellow, check the address whether across the page boundary,


bellow -> below

> +  //and split the data when across page boundary.

> +  if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) {

> +    Status = I2CRead (&stI2cDev, I2cOffset, sizeof (NIC_MAC_ADDRESS), (UINT8 *) &stMacDesc);

> +  } else {

> +    Status = I2CRead (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc);

> +    if (!(EFI_ERROR (Status))) {


Parantheses around EFI_ERROR not needed.

> +      Status |= I2CRead (

> +                  &stI2cDev,

> +                  I2cOffset + LessSizeOfPage,

> +                  sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage,

> +                  (UINT8 *) &stMacDesc + LessSizeOfPage

> +                );

> +    }

> +  }

> +  if (EFI_ERROR (Status)) {

> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cRead failed! p1=0x%x.\n",

> +            __FUNCTION__, __LINE__, Status));

> +    return Status;

> +  }

> +

> +  crc16 = make_crc_checksum (

> +            (UINT8 *) & (stMacDesc.MacLen),

> +            sizeof (stMacDesc.MacLen) + sizeof (stMacDesc.Mac)

> +          );

> +  if ((crc16 != stMacDesc.Crc16) || (0 == crc16)) {

> +    return EFI_NOT_FOUND;

> +  }

> +

> +  for (i = 0; i < MAC_ADDR_LEN; i++) {

> +    pucAddr[i] = stMacDesc.Mac[i];

> +  }

> +

> +  return EFI_SUCCESS;

> +}

> +

> +

> +EFI_STATUS

> +OemSetMacE2prom (

> +  IN UINT32 Port,

> +  IN UINT8 *pucAddr


Hungarian notation. Drop 'puc'.

> +  )

> +{

> +  I2C_DEVICE       stI2cDev = {0};


Hungarian notation. Drop 'st'.

> +  EFI_STATUS       Status;

> +  UINT16           I2cOffset;

> +  NIC_MAC_ADDRESS  stMacDesc = {0};


Hungarian notation. Drop 'st'.

> +  UINT32           i;


I.

> +  UINT16           RemainderMacOffset;

> +  UINT16           LessSizeOfPage;

> +

> +  i = 0;

> +  stMacDesc.MacLen = MAC_ADDR_LEN;

> +

> +  for (i = 0; i < MAC_ADDR_LEN; i++) {

> +    stMacDesc.Mac[i] = pucAddr[i];

> +  }

> +

> +  stMacDesc.Crc16 = make_crc_checksum (

> +                      (UINT8 *) & (stMacDesc.MacLen),

> +                      sizeof (stMacDesc.MacLen) + MAC_ADDR_LEN

> +                    );

> +

> +  Status = I2CInit (0, EEPROM_I2C_PORT, Normal);

> +  if (EFI_ERROR (Status)) {

> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n",

> +           __FUNCTION__, __LINE__, Status));

> +    return Status;

> +  }

> +

> +  I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS));

> +

> +  stI2cDev.DeviceType = DEVICE_TYPE_E2PROM;

> +  stI2cDev.Port = EEPROM_I2C_PORT;

> +  stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM;

> +  stI2cDev.Socket = 0;

> +  RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE;

> +  LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset;

> +  //The length of NIC_MAC_ADDRESS is 10 bytes long,

> +  //It surly less than EEPROM page size, so we could

> +  //code as bellow, check the address whether across the page boundary,


bellow -> below

> +  //and split the data when across page boundary.

> +  if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) {

> +    Status = I2CWrite (

> +               &stI2cDev,

> +               I2cOffset,

> +               sizeof (NIC_MAC_ADDRESS),

> +               (UINT8 *) &stMacDesc

> +             );

> +  } else {

> +    Status = I2CWrite (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc);

> +    if (!(EFI_ERROR (Status))) {


Parantheses around EFI_ERROR are not needed.

> +      Status |= I2CWrite (

> +                  &stI2cDev,

> +                  I2cOffset + LessSizeOfPage,

> +                  sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage,

> +                  (UINT8 *) &stMacDesc + LessSizeOfPage

> +                );

> +    }

> +  }

> +  if (EFI_ERROR (Status))

> +  {


Move { to previous line.

> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cWrite failed! p1=0x%x.\n",

> +            __FUNCTION__, __LINE__, Status));

> +    return Status;

> +  }

> +  return EFI_SUCCESS;

> +}

> +

> +EFI_STATUS

> +EFIAPI

> +OemGetMac (

> +  IN OUT EFI_MAC_ADDRESS *Mac,

> +  IN     UINTN           Port

> +  )

> +{

> +  EFI_STATUS Status;

> +

> +  if (NULL == Mac) {


No jeopardy tests. Turn the comparison around to the logical order.

> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n",

> +            __FUNCTION__, __LINE__));

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  Status = OemGetMacE2prom (Port, Mac->Addr);

> +  if ((EFI_ERROR (Status))) {


Parantheses around EFI_ERROR are not needed.

> +    DEBUG ((DEBUG_ERROR,

> +      "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n",

> +      __FUNCTION__, __LINE__, Status));

> +

> +    Mac->Addr[0] = 0x00;

> +    Mac->Addr[1] = 0x18;

> +    Mac->Addr[2] = 0x82;

> +    Mac->Addr[3] = 0x2F;

> +    Mac->Addr[4] = 0x02;

> +    Mac->Addr[5] = Port;


I'm not super happy about this. This would wreak havoc on any real
network.
Arguably, a server platform should just fail hard at this point.
I would certainly appreciate a Pcd making that an option.

Otherwise, some sort of proper scheme would need to be implemented:
using the 'locally administered range' of MAC addresses, and ensuring
addresses are only allocated after checking for possible duplicates on
the network.

> +    return EFI_SUCCESS;

> +  }

> +

> +  return EFI_SUCCESS;

> +}

> +

> +EFI_STATUS

> +EFIAPI

> +OemSetMac (

> +  IN EFI_MAC_ADDRESS *Mac,

> +  IN UINTN           Port

> +  )

> +{

> +  EFI_STATUS Status;

> +

> +  if (NULL == Mac) {


No jeopardy tests.

> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n",

> +            __FUNCTION__, __LINE__));

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  Status = OemSetMacE2prom (Port, Mac->Addr);

> +  if ((EFI_ERROR (Status))) {


Unneeded parantheses.

> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Set mac failed!\n", __FUNCTION__, __LINE__));

> +    return Status;

> +  }

> +

> +  return EFI_SUCCESS;

> +}

> +

> +UINT32

> +OemEthFindFirstSP (

> +  VOID

> +  )

> +{

> +  UINT32 i;


I.

> +

> +  for (i = 0; i < ETH_MAX_PORT; i++) {

> +    if (gEthPdtDesc[i].Valid == TRUE) {

> +      return i;

> +    }

> +  }

> +

> +  return ETH_INVALID;

> +}

> +

> +ETH_PRODUCT_DESC *

> +OemEthInit (

> +  UINT32 port

> +  )

> +{

> +  return (ETH_PRODUCT_DESC *)(&(gEthPdtDesc[port]));

> +}

> +

> +

> +BOOLEAN

> +OemIsInitEth (

> +  UINT32 Port

> +  )

> +{

> +  return TRUE;

> +}

> diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf

> new file mode 100644

> index 0000000000..ac849cb992

> --- /dev/null

> +++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf

> @@ -0,0 +1,35 @@

> +#/** @file

> +#

> +#    Copyright (c) 2018, Hisilicon Limited. All rights reserved.

> +#    Copyright (c) 2017, 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]

> +  INF_VERSION                    = 0x00010005


0x0001001a

> +  BASE_NAME                      = OemNicLib

> +  FILE_GUID                      = 520F872C-FFCF-4EF3-AC01-85BDB0816DCE

> +  MODULE_TYPE                    = BASE

> +  VERSION_STRING                 = 1.0

> +  LIBRARY_CLASS                  = OemNicLib

> +

> +[Sources.common]

> +  OemNicLib.c

> +

> +[Packages]

> +  MdePkg/MdePkg.dec

> +  MdeModulePkg/MdeModulePkg.dec

> +  ArmPkg/ArmPkg.dec

> +  Silicon/Hisilicon/HisiPkg.dec


Please sort alphabetically.

> +

> +[LibraryClasses]

> +  I2CLib

> +  CpldIoLib


Please sort alphabetically.

/
    Leif

> -- 

> 2.17.0

> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Ming Huang Aug. 9, 2018, 6:16 a.m. UTC | #2
在 8/3/2018 10:36 PM, Leif Lindholm 写道:
> On Tue, Jul 24, 2018 at 03:09:06PM +0800, Ming Huang wrote:
>> OemNicLib provide nic related api like GetMac,SetMac.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Ming Huang <ming.huang@linaro.org>
>> Signed-off-by: Heyi Guo <heyi.guo@linaro.org>
>> ---
>>  Platform/Hisilicon/D06/D06.dsc                         |   1 +
>>  Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c   | 571 ++++++++++++++++++++
>>  Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf |  35 ++
>>  3 files changed, 607 insertions(+)
>>
>> diff --git a/Platform/Hisilicon/D06/D06.dsc b/Platform/Hisilicon/D06/D06.dsc
>> index 43af043cfd..744a4a0d6d 100644
>> --- a/Platform/Hisilicon/D06/D06.dsc
>> +++ b/Platform/Hisilicon/D06/D06.dsc
>> @@ -91,6 +91,7 @@
>>  
>>    LpcLib|Silicon/Hisilicon/Hi1620/Library/LpcLibHi1620/LpcLib.inf
>>    SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf
>> +  OemNicLib|Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf
>>  !if $(SECURE_BOOT_ENABLE) == TRUE
>>    FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
>>  !endif
>> diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c
>> new file mode 100644
>> index 0000000000..55ed1625ce
>> --- /dev/null
>> +++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c
>> @@ -0,0 +1,571 @@
>> +/** @file
>> +*
>> +*  Copyright (c) 2018, Hisilicon Limited. All rights reserved.
>> +*  Copyright (c) 2017, 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.
>> +*
>> +**/
>> +
>> +#include <Uefi.h>
>> +#include <Library/CpldIoLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/I2CLib.h>
>> +#include <Library/IoLib.h>
>> +#include <Library/OemNicLib.h>
>> +
>> +#define CPU2_SFP2_100G_CARD_OFFSET   0x25
>> +#define CPU1_SFP1_LOCATE_OFFSET      0x16
>> +#define CPU1_SFP0_LOCATE_OFFSET      0x12
>> +#define CPU2_SFP1_LOCATE_OFFSET      0x21
>> +#define CPU2_SFP0_LOCATE_OFFSET      0x19
>> +#define CPU2_SFP2_10G_GE_CARD_OFFSET 0x25
>> +
>> +#define SFP_10G_SPEED   10
>> +#define SFP_25G_SPEED   25
>> +#define SFP_100G_SPEED  100
>> +#define SFP_GE_SPEED    1
>> +
>> +#define SFP_GE_SPEED_VAL_VENDOR_FINISAR 0x0C
>> +#define SFP_GE_SPEED_VAL                0x0D
>> +#define SFP_10G_SPEED_VAL               0x67
>> +#define SFP_25G_SPEED_VAL               0xFF
>> +
>> +#define CPU1_9545_I2C_ADDR 0x70
>> +#define CPU2_9545_I2C_ADDR 0x71
>> +
>> +#define FIBER_PRESENT     0
>> +#define CARD_PRESENT      1
>> +#define I2C_PORT_SFP      4
>> +#define CPU2_I2C_PORT_SFP 5
>> +
>> +#define SOCKET_0                 0
>> +#define SOCKET_1                 1
>> +#define EEPROM_I2C_PORT          4
>> +#define EEPROM_PAGE_SIZE         0x40
>> +#define MAC_ADDR_LEN             6
>> +#define I2C_OFFSET_EEPROM_ETH0   (0xc00)
>> +#define I2C_SLAVEADDR_EEPROM     (0x52)
>> +
>> +#pragma pack(1)
>> +typedef struct {
>> +  UINT16 Crc16;
>> +  UINT16 MacLen;
>> +  UINT8  Mac[MAC_ADDR_LEN];
>> +} NIC_MAC_ADDRESS;
>> +#pragma pack()
>> +
>> +ETH_PRODUCT_DESC gEthPdtDesc[ETH_MAX_PORT] =
>> +{
>> +    {TRUE,   ETH_SPEED_10KM,  ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID},
>> +    {TRUE,   ETH_SPEED_10KM,  ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID},
>> +    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID},
>> +    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID},
>> +    {TRUE,   ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 0},
>> +    {TRUE,   ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 1},
>> +    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID},
>> +    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID}
>> +};
>> +
>> +volatile unsigned char g_2pserveraddr[4][6] = {
> 
> VOLATILE UINT8.
> No '_' in variable name.
> Also, can we please have #defines for that 4 and 6?

OK, modify it in v2.

> 
>> +  {0x00, 0x18, 0x16, 0x29, 0x11, 0x00},
>> +  {0x00, 0x18, 0x16, 0x29, 0x11, 0x01},
>> +  {0x00, 0x18, 0x16, 0x29, 0x11, 0x02},
>> +  {0x00, 0x18, 0x16, 0x29, 0x11, 0x03}
>> +};
>> +
>> +UINT16 crc_tab[256] = {
> 
> CrcTable.

Modify it in v2.

> Hmm.
> This might be useful to add to a core library/driver/protocol. We
> don't appear to have it yet. This is another note to the universe.

Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ?
I think it's not enouth time to do this before Linaro 18.08 maybe.

> 
>> +  0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
>> +  0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
>> +  0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
>> +  0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
>> +  0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
>> +  0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
>> +  0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
>> +  0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
>> +  0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
>> +  0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
>> +  0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
>> +  0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
>> +  0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
>> +  0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
>> +  0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
>> +  0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
>> +  0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
>> +  0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
>> +  0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
>> +  0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
>> +  0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
>> +  0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
>> +  0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
>> +  0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
>> +  0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
>> +  0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
>> +  0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
>> +  0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
>> +  0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
>> +  0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
>> +  0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
>> +  0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0,
>> +};
>> +
>> +EFI_STATUS
>> +GetSfpSpeed (
>> +  UINT16 Socket,
>> +  UINT16 SfpNum,
>> +  UINT8* FiberSpeed
>> +  )
>> +{
>> +  EFI_STATUS  Status;
>> +  I2C_DEVICE  SpdDev;
>> +  UINT8       SpdReg;
>> +  UINT8       SfpSpeed;
>> +  UINT32      RegAddr;
>> +  UINT16      I2cAddr;
>> +  UINT32      SfpPort;
>> +
>> +  SfpSpeed = 0x0;
>> +  if(Socket == 1) {
> 
> Space before '('.
> Please add a descriptive #define for that 1.
> 
>> +    I2cAddr =  CPU2_9545_I2C_ADDR;
>> +    SfpPort = CPU2_I2C_PORT_SFP;
>> +  } else {
>> +    I2cAddr =  CPU1_9545_I2C_ADDR;
>> +    SfpPort = I2C_PORT_SFP;
>> +  }
>> +
>> +  Status = I2CInit (Socket, SfpPort, Normal);
>> +  if (EFI_ERROR (Status))
>> +  {
>> +      DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Socket%d Call I2CInit failed! p1=0x%x.\n",
>> +             __FUNCTION__, __LINE__, Socket, Status));
>> +      return Status;
>> +  }
>> +
>> +  SpdDev.Socket = Socket;
>> +  SpdDev.DeviceType         =  DEVICE_TYPE_SPD;
>> +  SpdDev.Port               =  SfpPort;
>> +  SpdDev.SlaveDeviceAddress =  I2cAddr;
>> +  RegAddr                   =  0x0;
>> +  SpdReg                    =  1 << (SfpNum - 1);
> 
> Please add descriptive #define.
> 
>> +
>> +  Status = I2CWrite (&SpdDev, RegAddr, 1, &SpdReg);
>> +  if (EFI_ERROR (Status)) {
>> +      DEBUG ((DEBUG_ERROR, "I2CWrite Error =%r.\n", Status));
>> +      return Status;
>> +  }
>> +
>> +  SpdDev.Socket = Socket;
>> +  SpdDev.DeviceType         =  DEVICE_TYPE_SPD;
>> +  SpdDev.Port               =  SfpPort;
>> +  SpdDev.SlaveDeviceAddress =  0x50;
> 
> Please add descriptive #define.
> 
>> +
>> +  RegAddr                   =  12;
> 
> Please add descriptive #define.
> 
>> +  Status = I2CRead (&SpdDev, RegAddr, 1, &SfpSpeed);
>> +  if (EFI_ERROR (Status)) {
>> +      DEBUG ((DEBUG_ERROR, "I2CRead Error =%r.\n", Status));
>> +      return Status;
>> +  }
>> +
>> +  DEBUG ((DEBUG_INFO, "BR, Nominal, Nominal signalling rate, SfpSpeed:    0x%x\n",
>> +         SfpSpeed));
>> +
>> +  if (SfpSpeed == SFP_10G_SPEED_VAL) {
>> +    *FiberSpeed = SFP_10G_SPEED;
>> +  } else if (SfpSpeed == SFP_25G_SPEED_VAL) {
>> +    *FiberSpeed = SFP_25G_SPEED;
>> +  } else if ((SfpSpeed == SFP_GE_SPEED_VAL) || (SfpSpeed == SFP_GE_SPEED_VAL_VENDOR_FINISAR)) {
> 
> Long line, please break.
> 
>> +    *FiberSpeed = SFP_GE_SPEED;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +//Fiber1Type/Fiber2Type/Fiber3Type return: SFP_10G_SPEED, SFP_100G_SPEED, SFP_GE_SPEED
>> +UINT32
>> +GetCpu2FiberType (
>> +  UINT8* Fiber1Type,
>> +  UINT8* Fiber2Type,
>> +  UINT8* Fiber100Ge
>> +  )
>> +{
>> +  EFI_STATUS  Status;
>> +  UINT16      SfpNum1;
>> +  UINT8       SfpSpeed1;
>> +  UINT16      SfpNum2;
>> +  UINT8       SfpSpeed2;
>> +
>> +  SfpNum1 = 0x1;
>> +  SfpSpeed1 = SFP_10G_SPEED;
>> +  SfpNum2 = 0x2;
>> +  SfpSpeed2 = SFP_10G_SPEED;
>> +  *Fiber100Ge = 0x0;
>> +  *Fiber1Type = SFP_10G_SPEED;
>> +  *Fiber2Type = SFP_10G_SPEED;
>> +
>> +  if ((ReadCpldReg (CPU2_SFP2_100G_CARD_OFFSET) & BIT7) == (CARD_PRESENT << 7)) {
> 
> Please add descriptively named helper macros or #defines (& BIT7, << 7).
> 
>> +    // 100 Ge card
>> +    *Fiber1Type = SFP_10G_SPEED;
>> +    *Fiber2Type = SFP_10G_SPEED;
>> +    *Fiber100Ge = SFP_100G_SPEED;
>> +    DEBUG ((DEBUG_ERROR,"Detect Fiber SFP_100G is Present, Set 100Ge\n"));
>> +  } else if ((ReadCpldReg (CPU2_SFP2_10G_GE_CARD_OFFSET) & BIT0) == CARD_PRESENT) {
> 
> Please add descriptively named helper macro or #define (& BIT0).
> 
>> +    *Fiber100Ge = 0x0;
>> +    *Fiber1Type = SFP_10G_SPEED;
>> +    *Fiber2Type = SFP_10G_SPEED;
>> +    if (ReadCpldReg (CPU2_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) {
>> +      // Fiber detected in CPU2 slot0, read speed via i2c
>> +      Status = GetSfpSpeed (SOCKET_1, SfpNum1, &SfpSpeed1);
>> +      if (EFI_ERROR (Status)) {
>> +        DEBUG((DEBUG_ERROR,
>> +               "Get Socket1 Sfp%d Speed Error: %r.\n",
>> +               SfpNum1,
>> +               Status));
>> +        return Status;
>> +      }
>> +      if (SfpSpeed1 == SFP_25G_SPEED) {
>> +        // P1 don't support 25G, so set speed to 10G
>> +        *Fiber1Type = SFP_10G_SPEED;
>> +      } else {
>> +        *Fiber1Type = SfpSpeed1;
>> +      }
>> +    } else {
>> +      // No fiber, set speed to 10G
>> +      *Fiber1Type = SFP_10G_SPEED;
>> +    }
>> +
>> +    if (ReadCpldReg (CPU2_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) {
>> +      // Fiber detected in CPU2 slot1, read speed via i2c
>> +      Status = GetSfpSpeed (SOCKET_1, SfpNum2, &SfpSpeed2);
>> +      if (EFI_ERROR (Status)) {
>> +        DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status));
>> +        return Status;
>> +      }
>> +      if (SfpSpeed2 == SFP_25G_SPEED) {
>> +        *Fiber2Type = SFP_10G_SPEED;
>> +      } else {
>> +        *Fiber2Type = SfpSpeed2;
>> +      }
>> +    } else {
>> +      // No fiber, set speed to 10G
>> +      *Fiber2Type = SFP_10G_SPEED;
>> +    }
>> +  } else {
>> +    // 100Ge/10Ge/Ge Fiber is not found.
>> +    *Fiber1Type = SFP_10G_SPEED;
>> +    *Fiber2Type = SFP_10G_SPEED;
>> +    *Fiber100Ge = 0x0;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +//Fiber1Type/Fiber2Type return: SFP_10G_SPEED, SFP_25G_SPEED, SFP_GE_SPEED
>> +UINT32
>> +GetCpu1FiberType (
>> +  UINT8* Fiber1Type,
>> +  UINT8* Fiber2Type
>> +  )
>> +{
>> +  EFI_STATUS  Status;
>> +  UINT16      SfpNum1;
>> +  UINT8       SfpSpeed1;
>> +  UINT16      SfpNum2;
>> +  UINT8       SfpSpeed2;
>> +
>> +  SfpNum1 = 0x1;
>> +  SfpSpeed1 = SFP_10G_SPEED;
>> +  SfpNum2 = 0x2;
>> +  SfpSpeed2 = SFP_10G_SPEED;
>> +  *Fiber1Type = SFP_10G_SPEED;
>> +  *Fiber2Type = SFP_10G_SPEED;
>> +  // Fiber detected in CPU1 slot0, read speed via i2c
>> +  if (ReadCpldReg (CPU1_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) {
>> +    Status = GetSfpSpeed (SOCKET_0, SfpNum1, &SfpSpeed1);
>> +    if (EFI_ERROR (Status)) {
>> +      DEBUG ((DEBUG_ERROR, "Get Socket0 Sfp%d Speed Error: %r.\n",
>> +              SfpNum1, Status));
>> +      return Status;
>> +    }
>> +    *Fiber1Type = SfpSpeed1;
>> +  } else {
>> +    *Fiber1Type = SFP_10G_SPEED;
>> +  }
>> +
>> +  // Fiber detected in CPU1 slot1, read speed via i2c
>> +  if (ReadCpldReg (CPU1_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) {
>> +    Status = GetSfpSpeed (SOCKET_0, SfpNum2, &SfpSpeed2);
>> +    if (EFI_ERROR (Status)) {
>> +      *Fiber2Type = SFP_10G_SPEED;
>> +      DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status));
>> +      return Status;
>> +    }
>> +    *Fiber2Type = SfpSpeed2;
>> +  } else {
>> +    *Fiber2Type = SFP_10G_SPEED;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +UINT16 make_crc_checksum (
> 
> MakeCrcChecksum
> 
>> +  UINT8 *buf,
> 
> Buffer.
> 
>> +  UINT32 len
> 
> Length.
> 
>> +  )
>> +{
>> +  UINT16 StartCRC = 0;
>> +
>> +  if (len > (512 * 1024)) {
> 
> SIZE_512KB?

Yes, SIZE_512KB is better.

> 
>> +    return 0;
>> +  }
>> +
>> +  if (buf == NULL) {
>> +    return 0;
>> +  }
>> +
>> +  while (len) {
>> +    StartCRC = crc_tab [((UINT8) ((StartCRC >> 8) & 0xff)) ^ *(buf++)] ^
>> +               ((UINT16) (StartCRC << 8));
>> +    len--;
>> +  }
>> +
>> +  return StartCRC;
>> +}
>> +
>> +
>> +EFI_STATUS
>> +OemGetMacE2prom(
>> +  IN  UINT32 Port,
>> +  OUT UINT8  *pucAddr
> 
> Hungarian notation. Drop 'puc'.
> 
>> +  )
>> +{
>> +  I2C_DEVICE       stI2cDev = {0};
> 
> Hungarian notation. Drop 'st'.
> 
>> +  EFI_STATUS       Status;
>> +  UINT16           I2cOffset;
>> +  UINT16           crc16;
> 
> Crc16.
> 
>> +  NIC_MAC_ADDRESS  stMacDesc = {0};
> 
> Hungarian notation. Drop 'st'.
> 
>> +  UINT16           RemainderMacOffset;
>> +  UINT16           LessSizeOfPage;
>> +  UINT32           i = 0;
> 
> I.
> 
>> +
>> +  Status = I2CInit (0, EEPROM_I2C_PORT, Normal);
>> +  if (EFI_ERROR (Status))
>> +  {
>> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n",
>> +            __FUNCTION__, __LINE__, Status));
>> +    return Status;
>> +  }
>> +
>> +  I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS));
>> +
>> +  stI2cDev.DeviceType = DEVICE_TYPE_E2PROM;
>> +  stI2cDev.Port = EEPROM_I2C_PORT;
>> +  stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM;
>> +  stI2cDev.Socket = 0;
>> +  RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE;
>> +  LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset;
>> +  //The length of NIC_MAC_ADDRESS is 10 bytes long,
>> +  //It surly less than EEPROM page size, so we could
>> +  //code as bellow, check the address whether across the page boundary,
> 
> bellow -> below
> 
>> +  //and split the data when across page boundary.
>> +  if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) {
>> +    Status = I2CRead (&stI2cDev, I2cOffset, sizeof (NIC_MAC_ADDRESS), (UINT8 *) &stMacDesc);
>> +  } else {
>> +    Status = I2CRead (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc);
>> +    if (!(EFI_ERROR (Status))) {
> 
> Parantheses around EFI_ERROR not needed.
> 
>> +      Status |= I2CRead (
>> +                  &stI2cDev,
>> +                  I2cOffset + LessSizeOfPage,
>> +                  sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage,
>> +                  (UINT8 *) &stMacDesc + LessSizeOfPage
>> +                );
>> +    }
>> +  }
>> +  if (EFI_ERROR (Status)) {
>> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cRead failed! p1=0x%x.\n",
>> +            __FUNCTION__, __LINE__, Status));
>> +    return Status;
>> +  }
>> +
>> +  crc16 = make_crc_checksum (
>> +            (UINT8 *) & (stMacDesc.MacLen),
>> +            sizeof (stMacDesc.MacLen) + sizeof (stMacDesc.Mac)
>> +          );
>> +  if ((crc16 != stMacDesc.Crc16) || (0 == crc16)) {
>> +    return EFI_NOT_FOUND;
>> +  }
>> +
>> +  for (i = 0; i < MAC_ADDR_LEN; i++) {
>> +    pucAddr[i] = stMacDesc.Mac[i];
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +
>> +EFI_STATUS
>> +OemSetMacE2prom (
>> +  IN UINT32 Port,
>> +  IN UINT8 *pucAddr
> 
> Hungarian notation. Drop 'puc'.
> 
>> +  )
>> +{
>> +  I2C_DEVICE       stI2cDev = {0};
> 
> Hungarian notation. Drop 'st'.
> 
>> +  EFI_STATUS       Status;
>> +  UINT16           I2cOffset;
>> +  NIC_MAC_ADDRESS  stMacDesc = {0};
> 
> Hungarian notation. Drop 'st'.
> 
>> +  UINT32           i;
> 
> I.
> 
>> +  UINT16           RemainderMacOffset;
>> +  UINT16           LessSizeOfPage;
>> +
>> +  i = 0;
>> +  stMacDesc.MacLen = MAC_ADDR_LEN;
>> +
>> +  for (i = 0; i < MAC_ADDR_LEN; i++) {
>> +    stMacDesc.Mac[i] = pucAddr[i];
>> +  }
>> +
>> +  stMacDesc.Crc16 = make_crc_checksum (
>> +                      (UINT8 *) & (stMacDesc.MacLen),
>> +                      sizeof (stMacDesc.MacLen) + MAC_ADDR_LEN
>> +                    );
>> +
>> +  Status = I2CInit (0, EEPROM_I2C_PORT, Normal);
>> +  if (EFI_ERROR (Status)) {
>> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n",
>> +           __FUNCTION__, __LINE__, Status));
>> +    return Status;
>> +  }
>> +
>> +  I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS));
>> +
>> +  stI2cDev.DeviceType = DEVICE_TYPE_E2PROM;
>> +  stI2cDev.Port = EEPROM_I2C_PORT;
>> +  stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM;
>> +  stI2cDev.Socket = 0;
>> +  RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE;
>> +  LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset;
>> +  //The length of NIC_MAC_ADDRESS is 10 bytes long,
>> +  //It surly less than EEPROM page size, so we could
>> +  //code as bellow, check the address whether across the page boundary,
> 
> bellow -> below
> 
>> +  //and split the data when across page boundary.
>> +  if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) {
>> +    Status = I2CWrite (
>> +               &stI2cDev,
>> +               I2cOffset,
>> +               sizeof (NIC_MAC_ADDRESS),
>> +               (UINT8 *) &stMacDesc
>> +             );
>> +  } else {
>> +    Status = I2CWrite (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc);
>> +    if (!(EFI_ERROR (Status))) {
> 
> Parantheses around EFI_ERROR are not needed.
> 
>> +      Status |= I2CWrite (
>> +                  &stI2cDev,
>> +                  I2cOffset + LessSizeOfPage,
>> +                  sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage,
>> +                  (UINT8 *) &stMacDesc + LessSizeOfPage
>> +                );
>> +    }
>> +  }
>> +  if (EFI_ERROR (Status))
>> +  {
> 
> Move { to previous line.
> 
>> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cWrite failed! p1=0x%x.\n",
>> +            __FUNCTION__, __LINE__, Status));
>> +    return Status;
>> +  }
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +OemGetMac (
>> +  IN OUT EFI_MAC_ADDRESS *Mac,
>> +  IN     UINTN           Port
>> +  )
>> +{
>> +  EFI_STATUS Status;
>> +
>> +  if (NULL == Mac) {
> 
> No jeopardy tests. Turn the comparison around to the logical order.
> 
>> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n",
>> +            __FUNCTION__, __LINE__));
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Status = OemGetMacE2prom (Port, Mac->Addr);
>> +  if ((EFI_ERROR (Status))) {
> 
> Parantheses around EFI_ERROR are not needed.
> 
>> +    DEBUG ((DEBUG_ERROR,
>> +      "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n",
>> +      __FUNCTION__, __LINE__, Status));
>> +
>> +    Mac->Addr[0] = 0x00;
>> +    Mac->Addr[1] = 0x18;
>> +    Mac->Addr[2] = 0x82;
>> +    Mac->Addr[3] = 0x2F;
>> +    Mac->Addr[4] = 0x02;
>> +    Mac->Addr[5] = Port;
> 
> I'm not super happy about this. This would wreak havoc on any real
> network.
> Arguably, a server platform should just fail hard at this point.
> I would certainly appreciate a Pcd making that an option.
> 
> Otherwise, some sort of proper scheme would need to be implemented:
> using the 'locally administered range' of MAC addresses, and ensuring
> addresses are only allocated after checking for possible duplicates on
> the network.

Do you suggest we should return EFI_NOT_FOUND here?

> 
>> +    return EFI_SUCCESS;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +OemSetMac (
>> +  IN EFI_MAC_ADDRESS *Mac,
>> +  IN UINTN           Port
>> +  )
>> +{
>> +  EFI_STATUS Status;
>> +
>> +  if (NULL == Mac) {
> 
> No jeopardy tests.
> 
>> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n",
>> +            __FUNCTION__, __LINE__));
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Status = OemSetMacE2prom (Port, Mac->Addr);
>> +  if ((EFI_ERROR (Status))) {
> 
> Unneeded parantheses.
> 
>> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Set mac failed!\n", __FUNCTION__, __LINE__));
>> +    return Status;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +UINT32
>> +OemEthFindFirstSP (
>> +  VOID
>> +  )
>> +{
>> +  UINT32 i;
> 
> I.
> 
>> +
>> +  for (i = 0; i < ETH_MAX_PORT; i++) {
>> +    if (gEthPdtDesc[i].Valid == TRUE) {
>> +      return i;
>> +    }
>> +  }
>> +
>> +  return ETH_INVALID;
>> +}
>> +
>> +ETH_PRODUCT_DESC *
>> +OemEthInit (
>> +  UINT32 port
>> +  )
>> +{
>> +  return (ETH_PRODUCT_DESC *)(&(gEthPdtDesc[port]));
>> +}
>> +
>> +
>> +BOOLEAN
>> +OemIsInitEth (
>> +  UINT32 Port
>> +  )
>> +{
>> +  return TRUE;
>> +}
>> diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf
>> new file mode 100644
>> index 0000000000..ac849cb992
>> --- /dev/null
>> +++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf
>> @@ -0,0 +1,35 @@
>> +#/** @file
>> +#
>> +#    Copyright (c) 2018, Hisilicon Limited. All rights reserved.
>> +#    Copyright (c) 2017, 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]
>> +  INF_VERSION                    = 0x00010005
> 
> 0x0001001a
> 
>> +  BASE_NAME                      = OemNicLib
>> +  FILE_GUID                      = 520F872C-FFCF-4EF3-AC01-85BDB0816DCE
>> +  MODULE_TYPE                    = BASE
>> +  VERSION_STRING                 = 1.0
>> +  LIBRARY_CLASS                  = OemNicLib
>> +
>> +[Sources.common]
>> +  OemNicLib.c
>> +
>> +[Packages]
>> +  MdePkg/MdePkg.dec
>> +  MdeModulePkg/MdeModulePkg.dec
>> +  ArmPkg/ArmPkg.dec
>> +  Silicon/Hisilicon/HisiPkg.dec
> 
> Please sort alphabetically.
> 
>> +
>> +[LibraryClasses]
>> +  I2CLib
>> +  CpldIoLib
> 
> Please sort alphabetically.

OK, and all other comments will apply in v2.
Thanks.

> 
> /
>     Leif
> 
>> -- 
>> 2.17.0
>>
Leif Lindholm Aug. 9, 2018, 10:19 a.m. UTC | #3
On Thu, Aug 09, 2018 at 02:16:49PM +0800, Ming wrote:
> >> +UINT16 crc_tab[256] = {

> > 

> > CrcTable.

> 

> Modify it in v2.

> 

> > Hmm.

> > This might be useful to add to a core library/driver/protocol. We

> > don't appear to have it yet. This is another note to the universe.

> 

> Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ?

> I think it's not enouth time to do this before Linaro 18.08 maybe.


Not needed for 18.08, but I would like to see the improvement made
afterwards.

> >> +EFI_STATUS

> >> +EFIAPI

> >> +OemGetMac (

> >> +  IN OUT EFI_MAC_ADDRESS *Mac,

> >> +  IN     UINTN           Port

> >> +  )

> >> +{

> >> +  EFI_STATUS Status;

> >> +

> >> +  if (NULL == Mac) {

> > 

> > No jeopardy tests. Turn the comparison around to the logical order.

> > 

> >> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n",

> >> +            __FUNCTION__, __LINE__));

> >> +    return EFI_INVALID_PARAMETER;

> >> +  }

> >> +

> >> +  Status = OemGetMacE2prom (Port, Mac->Addr);

> >> +  if ((EFI_ERROR (Status))) {

> > 

> > Parantheses around EFI_ERROR are not needed.

> > 

> >> +    DEBUG ((DEBUG_ERROR,

> >> +      "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n",

> >> +      __FUNCTION__, __LINE__, Status));

> >> +

> >> +    Mac->Addr[0] = 0x00;

> >> +    Mac->Addr[1] = 0x18;

> >> +    Mac->Addr[2] = 0x82;

> >> +    Mac->Addr[3] = 0x2F;

> >> +    Mac->Addr[4] = 0x02;

> >> +    Mac->Addr[5] = Port;

> > 

> > I'm not super happy about this. This would wreak havoc on any real

> > network.

> > Arguably, a server platform should just fail hard at this point.

> > I would certainly appreciate a Pcd making that an option.

> > 

> > Otherwise, some sort of proper scheme would need to be implemented:

> > using the 'locally administered range' of MAC addresses, and ensuring

> > addresses are only allocated after checking for possible duplicates on

> > the network.

> 

> Do you suggest we should return EFI_NOT_FOUND here?


Yes please.
It would be good if we could have some (common) code to handle the
fluke situation where you end up without your own MAC address.
(So that the node can boot up and report that it is broken.)
But it needs to be done in a reliable way, and that's too big a task
for 18.08.

/
    Leif
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Ming Huang Aug. 9, 2018, 2:41 p.m. UTC | #4
在 8/9/2018 6:19 PM, Leif Lindholm 写道:
> On Thu, Aug 09, 2018 at 02:16:49PM +0800, Ming wrote:
>>>> +UINT16 crc_tab[256] = {
>>>
>>> CrcTable.
>>
>> Modify it in v2.
>>
>>> Hmm.
>>> This might be useful to add to a core library/driver/protocol. We
>>> don't appear to have it yet. This is another note to the universe.
>>
>> Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ?
>> I think it's not enouth time to do this before Linaro 18.08 maybe.
> 
> Not needed for 18.08, but I would like to see the improvement made
> afterwards.

OK, I will do this after 18.08.

> 
>>>> +EFI_STATUS
>>>> +EFIAPI
>>>> +OemGetMac (
>>>> +  IN OUT EFI_MAC_ADDRESS *Mac,
>>>> +  IN     UINTN           Port
>>>> +  )
>>>> +{
>>>> +  EFI_STATUS Status;
>>>> +
>>>> +  if (NULL == Mac) {
>>>
>>> No jeopardy tests. Turn the comparison around to the logical order.
>>>
>>>> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n",
>>>> +            __FUNCTION__, __LINE__));
>>>> +    return EFI_INVALID_PARAMETER;
>>>> +  }
>>>> +
>>>> +  Status = OemGetMacE2prom (Port, Mac->Addr);
>>>> +  if ((EFI_ERROR (Status))) {
>>>
>>> Parantheses around EFI_ERROR are not needed.
>>>
>>>> +    DEBUG ((DEBUG_ERROR,
>>>> +      "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n",
>>>> +      __FUNCTION__, __LINE__, Status));
>>>> +
>>>> +    Mac->Addr[0] = 0x00;
>>>> +    Mac->Addr[1] = 0x18;
>>>> +    Mac->Addr[2] = 0x82;
>>>> +    Mac->Addr[3] = 0x2F;
>>>> +    Mac->Addr[4] = 0x02;
>>>> +    Mac->Addr[5] = Port;
>>>
>>> I'm not super happy about this. This would wreak havoc on any real
>>> network.
>>> Arguably, a server platform should just fail hard at this point.
>>> I would certainly appreciate a Pcd making that an option.
>>>
>>> Otherwise, some sort of proper scheme would need to be implemented:
>>> using the 'locally administered range' of MAC addresses, and ensuring
>>> addresses are only allocated after checking for possible duplicates on
>>> the network.
>>
>> Do you suggest we should return EFI_NOT_FOUND here?
> 
> Yes please.
> It would be good if we could have some (common) code to handle the
> fluke situation where you end up without your own MAC address.
> (So that the node can boot up and report that it is broken.)
> But it needs to be done in a reliable way, and that's too big a task
> for 18.08.

I will think about this after 18.08.
Thanks.

> 
> /
>     Leif
>
Ming Huang Aug. 14, 2018, 2:38 a.m. UTC | #5
在 8/9/2018 6:19 PM, Leif Lindholm 写道:
> On Thu, Aug 09, 2018 at 02:16:49PM +0800, Ming wrote:
>>>> +UINT16 crc_tab[256] = {
>>>
>>> CrcTable.
>>
>> Modify it in v2.
>>
>>> Hmm.
>>> This might be useful to add to a core library/driver/protocol. We
>>> don't appear to have it yet. This is another note to the universe.
>>
>> Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ?
>> I think it's not enouth time to do this before Linaro 18.08 maybe.
> 
> Not needed for 18.08, but I would like to see the improvement made
> afterwards.
> 
>>>> +EFI_STATUS
>>>> +EFIAPI
>>>> +OemGetMac (
>>>> +  IN OUT EFI_MAC_ADDRESS *Mac,
>>>> +  IN     UINTN           Port
>>>> +  )
>>>> +{
>>>> +  EFI_STATUS Status;
>>>> +
>>>> +  if (NULL == Mac) {
>>>
>>> No jeopardy tests. Turn the comparison around to the logical order.
>>>
>>>> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n",
>>>> +            __FUNCTION__, __LINE__));
>>>> +    return EFI_INVALID_PARAMETER;
>>>> +  }
>>>> +
>>>> +  Status = OemGetMacE2prom (Port, Mac->Addr);
>>>> +  if ((EFI_ERROR (Status))) {
>>>
>>> Parantheses around EFI_ERROR are not needed.
>>>
>>>> +    DEBUG ((DEBUG_ERROR,
>>>> +      "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n",
>>>> +      __FUNCTION__, __LINE__, Status));
>>>> +
>>>> +    Mac->Addr[0] = 0x00;
>>>> +    Mac->Addr[1] = 0x18;
>>>> +    Mac->Addr[2] = 0x82;
>>>> +    Mac->Addr[3] = 0x2F;
>>>> +    Mac->Addr[4] = 0x02;
>>>> +    Mac->Addr[5] = Port;
>>>
>>> I'm not super happy about this. This would wreak havoc on any real
>>> network.
>>> Arguably, a server platform should just fail hard at this point.
>>> I would certainly appreciate a Pcd making that an option.
>>>
>>> Otherwise, some sort of proper scheme would need to be implemented:
>>> using the 'locally administered range' of MAC addresses, and ensuring
>>> addresses are only allocated after checking for possible duplicates on
>>> the network.
>>
>> Do you suggest we should return EFI_NOT_FOUND here?
> 
> Yes please.
> It would be good if we could have some (common) code to handle the
> fluke situation where you end up without your own MAC address.
> (So that the node can boot up and report that it is broken.)
> But it needs to be done in a reliable way, and that's too big a task
> for 18.08.

I found some modules which invoke OemGetMac() don't judge the Status of
OemGetMac, so it may cause some issue now if changing to EFI_NOT_FOUND.
How about change it while we handle the fluke situation after 18.08 ?

> 
> /
>     Leif
>
Leif Lindholm Aug. 14, 2018, 3:48 p.m. UTC | #6
On Tue, Aug 14, 2018 at 10:38:14AM +0800, Ming wrote:
> 
> 
> 在 8/9/2018 6:19 PM, Leif Lindholm 写道:
> > On Thu, Aug 09, 2018 at 02:16:49PM +0800, Ming wrote:
> >>>> +UINT16 crc_tab[256] = {
> >>>
> >>> CrcTable.
> >>
> >> Modify it in v2.
> >>
> >>> Hmm.
> >>> This might be useful to add to a core library/driver/protocol. We
> >>> don't appear to have it yet. This is another note to the universe.
> >>
> >> Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ?
> >> I think it's not enouth time to do this before Linaro 18.08 maybe.
> > 
> > Not needed for 18.08, but I would like to see the improvement made
> > afterwards.
> > 
> >>>> +EFI_STATUS
> >>>> +EFIAPI
> >>>> +OemGetMac (
> >>>> +  IN OUT EFI_MAC_ADDRESS *Mac,
> >>>> +  IN     UINTN           Port
> >>>> +  )
> >>>> +{
> >>>> +  EFI_STATUS Status;
> >>>> +
> >>>> +  if (NULL == Mac) {
> >>>
> >>> No jeopardy tests. Turn the comparison around to the logical order.
> >>>
> >>>> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n",
> >>>> +            __FUNCTION__, __LINE__));
> >>>> +    return EFI_INVALID_PARAMETER;
> >>>> +  }
> >>>> +
> >>>> +  Status = OemGetMacE2prom (Port, Mac->Addr);
> >>>> +  if ((EFI_ERROR (Status))) {
> >>>
> >>> Parantheses around EFI_ERROR are not needed.
> >>>
> >>>> +    DEBUG ((DEBUG_ERROR,
> >>>> +      "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n",
> >>>> +      __FUNCTION__, __LINE__, Status));
> >>>> +
> >>>> +    Mac->Addr[0] = 0x00;
> >>>> +    Mac->Addr[1] = 0x18;
> >>>> +    Mac->Addr[2] = 0x82;
> >>>> +    Mac->Addr[3] = 0x2F;
> >>>> +    Mac->Addr[4] = 0x02;
> >>>> +    Mac->Addr[5] = Port;
> >>>
> >>> I'm not super happy about this. This would wreak havoc on any real
> >>> network.
> >>> Arguably, a server platform should just fail hard at this point.
> >>> I would certainly appreciate a Pcd making that an option.
> >>>
> >>> Otherwise, some sort of proper scheme would need to be implemented:
> >>> using the 'locally administered range' of MAC addresses, and ensuring
> >>> addresses are only allocated after checking for possible duplicates on
> >>> the network.
> >>
> >> Do you suggest we should return EFI_NOT_FOUND here?
> > 
> > Yes please.
> > It would be good if we could have some (common) code to handle the
> > fluke situation where you end up without your own MAC address.
> > (So that the node can boot up and report that it is broken.)
> > But it needs to be done in a reliable way, and that's too big a task
> > for 18.08.
> 
> I found some modules which invoke OemGetMac() don't judge the Status of
> OemGetMac, so it may cause some issue now if changing to EFI_NOT_FOUND.
> How about change it while we handle the fluke situation after 18.08 ?

We cannot release 18.08 with known bugs.
And not checking return value is a bug.

I presume you mean that these calling functions are inside HwPkg?

The alternative would be to ensure the function does not return.
But I would not recommend that.

/
    Leif
Ming Huang Aug. 15, 2018, 11:08 a.m. UTC | #7
在 8/14/2018 11:48 PM, Leif Lindholm 写道:
> On Tue, Aug 14, 2018 at 10:38:14AM +0800, Ming wrote:
>>
>>
>> 在 8/9/2018 6:19 PM, Leif Lindholm 写道:
>>> On Thu, Aug 09, 2018 at 02:16:49PM +0800, Ming wrote:
>>>>>> +UINT16 crc_tab[256] = {
>>>>>
>>>>> CrcTable.
>>>>
>>>> Modify it in v2.
>>>>
>>>>> Hmm.
>>>>> This might be useful to add to a core library/driver/protocol. We
>>>>> don't appear to have it yet. This is another note to the universe.
>>>>
>>>> Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ?
>>>> I think it's not enouth time to do this before Linaro 18.08 maybe.
>>>
>>> Not needed for 18.08, but I would like to see the improvement made
>>> afterwards.
>>>
>>>>>> +EFI_STATUS
>>>>>> +EFIAPI
>>>>>> +OemGetMac (
>>>>>> +  IN OUT EFI_MAC_ADDRESS *Mac,
>>>>>> +  IN     UINTN           Port
>>>>>> +  )
>>>>>> +{
>>>>>> +  EFI_STATUS Status;
>>>>>> +
>>>>>> +  if (NULL == Mac) {
>>>>>
>>>>> No jeopardy tests. Turn the comparison around to the logical order.
>>>>>
>>>>>> +    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n",
>>>>>> +            __FUNCTION__, __LINE__));
>>>>>> +    return EFI_INVALID_PARAMETER;
>>>>>> +  }
>>>>>> +
>>>>>> +  Status = OemGetMacE2prom (Port, Mac->Addr);
>>>>>> +  if ((EFI_ERROR (Status))) {
>>>>>
>>>>> Parantheses around EFI_ERROR are not needed.
>>>>>
>>>>>> +    DEBUG ((DEBUG_ERROR,
>>>>>> +      "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n",
>>>>>> +      __FUNCTION__, __LINE__, Status));
>>>>>> +
>>>>>> +    Mac->Addr[0] = 0x00;
>>>>>> +    Mac->Addr[1] = 0x18;
>>>>>> +    Mac->Addr[2] = 0x82;
>>>>>> +    Mac->Addr[3] = 0x2F;
>>>>>> +    Mac->Addr[4] = 0x02;
>>>>>> +    Mac->Addr[5] = Port;
>>>>>
>>>>> I'm not super happy about this. This would wreak havoc on any real
>>>>> network.
>>>>> Arguably, a server platform should just fail hard at this point.
>>>>> I would certainly appreciate a Pcd making that an option.
>>>>>
>>>>> Otherwise, some sort of proper scheme would need to be implemented:
>>>>> using the 'locally administered range' of MAC addresses, and ensuring
>>>>> addresses are only allocated after checking for possible duplicates on
>>>>> the network.
>>>>
>>>> Do you suggest we should return EFI_NOT_FOUND here?
>>>
>>> Yes please.
>>> It would be good if we could have some (common) code to handle the
>>> fluke situation where you end up without your own MAC address.
>>> (So that the node can boot up and report that it is broken.)
>>> But it needs to be done in a reliable way, and that's too big a task
>>> for 18.08.
>>
>> I found some modules which invoke OemGetMac() don't judge the Status of
>> OemGetMac, so it may cause some issue now if changing to EFI_NOT_FOUND.
>> How about change it while we handle the fluke situation after 18.08 ?
> 
> We cannot release 18.08 with known bugs.
> And not checking return value is a bug.
> 
> I presume you mean that these calling functions are inside HwPkg?

Yes.

All D06 board will burn a Mac to eeprom before delivery and there is a
command (SetMac) to write a Mac.

For handling the fluke situation, we think there are several ways:
1 Initialize Mac to 0xFF;
  Kernel seems will create a random Mac while the Mac is 0xFF.
2 Make a Mac from ArmReadCntPct() and gTR->GetTime();
3 Make a locally administered Mac from ArmReadCntPct() and gTR->GetTime();

The 2nd is the way our product project use to handle the fluke situation.
What is your suggestion?

> 
> The alternative would be to ensure the function does not return.
> But I would not recommend that.
> 
> /
>     Leif
>
Leif Lindholm Aug. 15, 2018, 1:22 p.m. UTC | #8
On Wed, Aug 15, 2018 at 07:08:33PM +0800, Ming wrote:
> >>> Yes please.

> >>> It would be good if we could have some (common) code to handle the

> >>> fluke situation where you end up without your own MAC address.

> >>> (So that the node can boot up and report that it is broken.)

> >>> But it needs to be done in a reliable way, and that's too big a task

> >>> for 18.08.

> >>

> >> I found some modules which invoke OemGetMac() don't judge the Status of

> >> OemGetMac, so it may cause some issue now if changing to EFI_NOT_FOUND.

> >> How about change it while we handle the fluke situation after 18.08 ?

> > 

> > We cannot release 18.08 with known bugs.

> > And not checking return value is a bug.

> > 

> > I presume you mean that these calling functions are inside HwPkg?

> 

> Yes.

> 

> All D06 board will burn a Mac to eeprom before delivery and there is a

> command (SetMac) to write a Mac.

> 

> For handling the fluke situation, we think there are several ways:

> 1 Initialize Mac to 0xFF;

>   Kernel seems will create a random Mac while the Mac is 0xFF.


I have no objections to that, but it would prevent from netbooting.

But being unable to read the eeprom is a serious hw failure. So my gut
feeling is that this should prevent the system from booting
completely. If you want to make it possible to boot at all, and don't
mind giving up netbooting for systems with known hardware failure, I
think that's acceptable.

> 2 Make a Mac from ArmReadCntPct() and gTR->GetTime();

> 3 Make a locally administered Mac from ArmReadCntPct() and gTR->GetTime();

> 

> The 2nd is the way our product project use to handle the fluke situation.

> What is your suggestion?


2 is not OK.

3 would be totally valid, but is basically just "do 2 properly".

And doing 2 properly means doing ARP lookups to ensure we don't have
any duplicate MACs on the current network segment. Which is more
effort (and probably functionality we want to get into edk2 core).

My recommendation for 18.08 would be doing 1. Then we have time to
discuss nicer fallback options afterwards.

/
    Leif
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Ming Huang Aug. 15, 2018, 2:16 p.m. UTC | #9
在 8/15/2018 9:22 PM, Leif Lindholm 写道:
> On Wed, Aug 15, 2018 at 07:08:33PM +0800, Ming wrote:
>>>>> Yes please.
>>>>> It would be good if we could have some (common) code to handle the
>>>>> fluke situation where you end up without your own MAC address.
>>>>> (So that the node can boot up and report that it is broken.)
>>>>> But it needs to be done in a reliable way, and that's too big a task
>>>>> for 18.08.
>>>>
>>>> I found some modules which invoke OemGetMac() don't judge the Status of
>>>> OemGetMac, so it may cause some issue now if changing to EFI_NOT_FOUND.
>>>> How about change it while we handle the fluke situation after 18.08 ?
>>>
>>> We cannot release 18.08 with known bugs.
>>> And not checking return value is a bug.
>>>
>>> I presume you mean that these calling functions are inside HwPkg?
>>
>> Yes.
>>
>> All D06 board will burn a Mac to eeprom before delivery and there is a
>> command (SetMac) to write a Mac.
>>
>> For handling the fluke situation, we think there are several ways:
>> 1 Initialize Mac to 0xFF;
>>   Kernel seems will create a random Mac while the Mac is 0xFF.
> 
> I have no objections to that, but it would prevent from netbooting.
> 
> But being unable to read the eeprom is a serious hw failure. So my gut
> feeling is that this should prevent the system from booting
> completely. If you want to make it possible to boot at all, and don't
> mind giving up netbooting for systems with known hardware failure, I
> think that's acceptable.
> 
>> 2 Make a Mac from ArmReadCntPct() and gTR->GetTime();
>> 3 Make a locally administered Mac from ArmReadCntPct() and gTR->GetTime();
>>
>> The 2nd is the way our product project use to handle the fluke situation.
>> What is your suggestion?
> 
> 2 is not OK.
> 
> 3 would be totally valid, but is basically just "do 2 properly".
> 
> And doing 2 properly means doing ARP lookups to ensure we don't have
> any duplicate MACs on the current network segment. Which is more
> effort (and probably functionality we want to get into edk2 core).
> 
> My recommendation for 18.08 would be doing 1. Then we have time to
> discuss nicer fallback options afterwards.

OK, doing 1 for 18.08.
I will send v3 patch set ASAP.
Thanks.


> 
> /
>     Leif
>
diff mbox series

Patch

diff --git a/Platform/Hisilicon/D06/D06.dsc b/Platform/Hisilicon/D06/D06.dsc
index 43af043cfd..744a4a0d6d 100644
--- a/Platform/Hisilicon/D06/D06.dsc
+++ b/Platform/Hisilicon/D06/D06.dsc
@@ -91,6 +91,7 @@ 
 
   LpcLib|Silicon/Hisilicon/Hi1620/Library/LpcLibHi1620/LpcLib.inf
   SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf
+  OemNicLib|Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf
 !if $(SECURE_BOOT_ENABLE) == TRUE
   FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
 !endif
diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c
new file mode 100644
index 0000000000..55ed1625ce
--- /dev/null
+++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c
@@ -0,0 +1,571 @@ 
+/** @file
+*
+*  Copyright (c) 2018, Hisilicon Limited. All rights reserved.
+*  Copyright (c) 2017, 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.
+*
+**/
+
+#include <Uefi.h>
+#include <Library/CpldIoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/I2CLib.h>
+#include <Library/IoLib.h>
+#include <Library/OemNicLib.h>
+
+#define CPU2_SFP2_100G_CARD_OFFSET   0x25
+#define CPU1_SFP1_LOCATE_OFFSET      0x16
+#define CPU1_SFP0_LOCATE_OFFSET      0x12
+#define CPU2_SFP1_LOCATE_OFFSET      0x21
+#define CPU2_SFP0_LOCATE_OFFSET      0x19
+#define CPU2_SFP2_10G_GE_CARD_OFFSET 0x25
+
+#define SFP_10G_SPEED   10
+#define SFP_25G_SPEED   25
+#define SFP_100G_SPEED  100
+#define SFP_GE_SPEED    1
+
+#define SFP_GE_SPEED_VAL_VENDOR_FINISAR 0x0C
+#define SFP_GE_SPEED_VAL                0x0D
+#define SFP_10G_SPEED_VAL               0x67
+#define SFP_25G_SPEED_VAL               0xFF
+
+#define CPU1_9545_I2C_ADDR 0x70
+#define CPU2_9545_I2C_ADDR 0x71
+
+#define FIBER_PRESENT     0
+#define CARD_PRESENT      1
+#define I2C_PORT_SFP      4
+#define CPU2_I2C_PORT_SFP 5
+
+#define SOCKET_0                 0
+#define SOCKET_1                 1
+#define EEPROM_I2C_PORT          4
+#define EEPROM_PAGE_SIZE         0x40
+#define MAC_ADDR_LEN             6
+#define I2C_OFFSET_EEPROM_ETH0   (0xc00)
+#define I2C_SLAVEADDR_EEPROM     (0x52)
+
+#pragma pack(1)
+typedef struct {
+  UINT16 Crc16;
+  UINT16 MacLen;
+  UINT8  Mac[MAC_ADDR_LEN];
+} NIC_MAC_ADDRESS;
+#pragma pack()
+
+ETH_PRODUCT_DESC gEthPdtDesc[ETH_MAX_PORT] =
+{
+    {TRUE,   ETH_SPEED_10KM,  ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID},
+    {TRUE,   ETH_SPEED_10KM,  ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID},
+    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID},
+    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID},
+    {TRUE,   ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 0},
+    {TRUE,   ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 1},
+    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID},
+    {FALSE,  ETH_INVALID,     ETH_INVALID,     ETH_INVALID, ETH_INVALID}
+};
+
+volatile unsigned char g_2pserveraddr[4][6] = {
+  {0x00, 0x18, 0x16, 0x29, 0x11, 0x00},
+  {0x00, 0x18, 0x16, 0x29, 0x11, 0x01},
+  {0x00, 0x18, 0x16, 0x29, 0x11, 0x02},
+  {0x00, 0x18, 0x16, 0x29, 0x11, 0x03}
+};
+
+UINT16 crc_tab[256] = {
+  0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+  0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
+  0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
+  0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
+  0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
+  0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
+  0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
+  0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
+  0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
+  0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
+  0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
+  0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
+  0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
+  0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
+  0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
+  0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
+  0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
+  0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
+  0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
+  0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
+  0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
+  0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+  0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
+  0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
+  0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
+  0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
+  0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
+  0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
+  0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
+  0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
+  0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
+  0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0,
+};
+
+EFI_STATUS
+GetSfpSpeed (
+  UINT16 Socket,
+  UINT16 SfpNum,
+  UINT8* FiberSpeed
+  )
+{
+  EFI_STATUS  Status;
+  I2C_DEVICE  SpdDev;
+  UINT8       SpdReg;
+  UINT8       SfpSpeed;
+  UINT32      RegAddr;
+  UINT16      I2cAddr;
+  UINT32      SfpPort;
+
+  SfpSpeed = 0x0;
+  if(Socket == 1) {
+    I2cAddr =  CPU2_9545_I2C_ADDR;
+    SfpPort = CPU2_I2C_PORT_SFP;
+  } else {
+    I2cAddr =  CPU1_9545_I2C_ADDR;
+    SfpPort = I2C_PORT_SFP;
+  }
+
+  Status = I2CInit (Socket, SfpPort, Normal);
+  if (EFI_ERROR (Status))
+  {
+      DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Socket%d Call I2CInit failed! p1=0x%x.\n",
+             __FUNCTION__, __LINE__, Socket, Status));
+      return Status;
+  }
+
+  SpdDev.Socket = Socket;
+  SpdDev.DeviceType         =  DEVICE_TYPE_SPD;
+  SpdDev.Port               =  SfpPort;
+  SpdDev.SlaveDeviceAddress =  I2cAddr;
+  RegAddr                   =  0x0;
+  SpdReg                    =  1 << (SfpNum - 1);
+
+  Status = I2CWrite (&SpdDev, RegAddr, 1, &SpdReg);
+  if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "I2CWrite Error =%r.\n", Status));
+      return Status;
+  }
+
+  SpdDev.Socket = Socket;
+  SpdDev.DeviceType         =  DEVICE_TYPE_SPD;
+  SpdDev.Port               =  SfpPort;
+  SpdDev.SlaveDeviceAddress =  0x50;
+
+  RegAddr                   =  12;
+  Status = I2CRead (&SpdDev, RegAddr, 1, &SfpSpeed);
+  if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "I2CRead Error =%r.\n", Status));
+      return Status;
+  }
+
+  DEBUG ((DEBUG_INFO, "BR, Nominal, Nominal signalling rate, SfpSpeed:    0x%x\n",
+         SfpSpeed));
+
+  if (SfpSpeed == SFP_10G_SPEED_VAL) {
+    *FiberSpeed = SFP_10G_SPEED;
+  } else if (SfpSpeed == SFP_25G_SPEED_VAL) {
+    *FiberSpeed = SFP_25G_SPEED;
+  } else if ((SfpSpeed == SFP_GE_SPEED_VAL) || (SfpSpeed == SFP_GE_SPEED_VAL_VENDOR_FINISAR)) {
+    *FiberSpeed = SFP_GE_SPEED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+//Fiber1Type/Fiber2Type/Fiber3Type return: SFP_10G_SPEED, SFP_100G_SPEED, SFP_GE_SPEED
+UINT32
+GetCpu2FiberType (
+  UINT8* Fiber1Type,
+  UINT8* Fiber2Type,
+  UINT8* Fiber100Ge
+  )
+{
+  EFI_STATUS  Status;
+  UINT16      SfpNum1;
+  UINT8       SfpSpeed1;
+  UINT16      SfpNum2;
+  UINT8       SfpSpeed2;
+
+  SfpNum1 = 0x1;
+  SfpSpeed1 = SFP_10G_SPEED;
+  SfpNum2 = 0x2;
+  SfpSpeed2 = SFP_10G_SPEED;
+  *Fiber100Ge = 0x0;
+  *Fiber1Type = SFP_10G_SPEED;
+  *Fiber2Type = SFP_10G_SPEED;
+
+  if ((ReadCpldReg (CPU2_SFP2_100G_CARD_OFFSET) & BIT7) == (CARD_PRESENT << 7)) {
+    // 100 Ge card
+    *Fiber1Type = SFP_10G_SPEED;
+    *Fiber2Type = SFP_10G_SPEED;
+    *Fiber100Ge = SFP_100G_SPEED;
+    DEBUG ((DEBUG_ERROR,"Detect Fiber SFP_100G is Present, Set 100Ge\n"));
+  } else if ((ReadCpldReg (CPU2_SFP2_10G_GE_CARD_OFFSET) & BIT0) == CARD_PRESENT) {
+    *Fiber100Ge = 0x0;
+    *Fiber1Type = SFP_10G_SPEED;
+    *Fiber2Type = SFP_10G_SPEED;
+    if (ReadCpldReg (CPU2_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) {
+      // Fiber detected in CPU2 slot0, read speed via i2c
+      Status = GetSfpSpeed (SOCKET_1, SfpNum1, &SfpSpeed1);
+      if (EFI_ERROR (Status)) {
+        DEBUG((DEBUG_ERROR,
+               "Get Socket1 Sfp%d Speed Error: %r.\n",
+               SfpNum1,
+               Status));
+        return Status;
+      }
+      if (SfpSpeed1 == SFP_25G_SPEED) {
+        // P1 don't support 25G, so set speed to 10G
+        *Fiber1Type = SFP_10G_SPEED;
+      } else {
+        *Fiber1Type = SfpSpeed1;
+      }
+    } else {
+      // No fiber, set speed to 10G
+      *Fiber1Type = SFP_10G_SPEED;
+    }
+
+    if (ReadCpldReg (CPU2_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) {
+      // Fiber detected in CPU2 slot1, read speed via i2c
+      Status = GetSfpSpeed (SOCKET_1, SfpNum2, &SfpSpeed2);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status));
+        return Status;
+      }
+      if (SfpSpeed2 == SFP_25G_SPEED) {
+        *Fiber2Type = SFP_10G_SPEED;
+      } else {
+        *Fiber2Type = SfpSpeed2;
+      }
+    } else {
+      // No fiber, set speed to 10G
+      *Fiber2Type = SFP_10G_SPEED;
+    }
+  } else {
+    // 100Ge/10Ge/Ge Fiber is not found.
+    *Fiber1Type = SFP_10G_SPEED;
+    *Fiber2Type = SFP_10G_SPEED;
+    *Fiber100Ge = 0x0;
+  }
+
+  return EFI_SUCCESS;
+}
+
+//Fiber1Type/Fiber2Type return: SFP_10G_SPEED, SFP_25G_SPEED, SFP_GE_SPEED
+UINT32
+GetCpu1FiberType (
+  UINT8* Fiber1Type,
+  UINT8* Fiber2Type
+  )
+{
+  EFI_STATUS  Status;
+  UINT16      SfpNum1;
+  UINT8       SfpSpeed1;
+  UINT16      SfpNum2;
+  UINT8       SfpSpeed2;
+
+  SfpNum1 = 0x1;
+  SfpSpeed1 = SFP_10G_SPEED;
+  SfpNum2 = 0x2;
+  SfpSpeed2 = SFP_10G_SPEED;
+  *Fiber1Type = SFP_10G_SPEED;
+  *Fiber2Type = SFP_10G_SPEED;
+  // Fiber detected in CPU1 slot0, read speed via i2c
+  if (ReadCpldReg (CPU1_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) {
+    Status = GetSfpSpeed (SOCKET_0, SfpNum1, &SfpSpeed1);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Get Socket0 Sfp%d Speed Error: %r.\n",
+              SfpNum1, Status));
+      return Status;
+    }
+    *Fiber1Type = SfpSpeed1;
+  } else {
+    *Fiber1Type = SFP_10G_SPEED;
+  }
+
+  // Fiber detected in CPU1 slot1, read speed via i2c
+  if (ReadCpldReg (CPU1_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) {
+    Status = GetSfpSpeed (SOCKET_0, SfpNum2, &SfpSpeed2);
+    if (EFI_ERROR (Status)) {
+      *Fiber2Type = SFP_10G_SPEED;
+      DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status));
+      return Status;
+    }
+    *Fiber2Type = SfpSpeed2;
+  } else {
+    *Fiber2Type = SFP_10G_SPEED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+UINT16 make_crc_checksum (
+  UINT8 *buf,
+  UINT32 len
+  )
+{
+  UINT16 StartCRC = 0;
+
+  if (len > (512 * 1024)) {
+    return 0;
+  }
+
+  if (buf == NULL) {
+    return 0;
+  }
+
+  while (len) {
+    StartCRC = crc_tab [((UINT8) ((StartCRC >> 8) & 0xff)) ^ *(buf++)] ^
+               ((UINT16) (StartCRC << 8));
+    len--;
+  }
+
+  return StartCRC;
+}
+
+
+EFI_STATUS
+OemGetMacE2prom(
+  IN  UINT32 Port,
+  OUT UINT8  *pucAddr
+  )
+{
+  I2C_DEVICE       stI2cDev = {0};
+  EFI_STATUS       Status;
+  UINT16           I2cOffset;
+  UINT16           crc16;
+  NIC_MAC_ADDRESS  stMacDesc = {0};
+  UINT16           RemainderMacOffset;
+  UINT16           LessSizeOfPage;
+  UINT32           i = 0;
+
+  Status = I2CInit (0, EEPROM_I2C_PORT, Normal);
+  if (EFI_ERROR (Status))
+  {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n",
+            __FUNCTION__, __LINE__, Status));
+    return Status;
+  }
+
+  I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS));
+
+  stI2cDev.DeviceType = DEVICE_TYPE_E2PROM;
+  stI2cDev.Port = EEPROM_I2C_PORT;
+  stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM;
+  stI2cDev.Socket = 0;
+  RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE;
+  LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset;
+  //The length of NIC_MAC_ADDRESS is 10 bytes long,
+  //It surly less than EEPROM page size, so we could
+  //code as bellow, check the address whether across the page boundary,
+  //and split the data when across page boundary.
+  if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) {
+    Status = I2CRead (&stI2cDev, I2cOffset, sizeof (NIC_MAC_ADDRESS), (UINT8 *) &stMacDesc);
+  } else {
+    Status = I2CRead (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc);
+    if (!(EFI_ERROR (Status))) {
+      Status |= I2CRead (
+                  &stI2cDev,
+                  I2cOffset + LessSizeOfPage,
+                  sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage,
+                  (UINT8 *) &stMacDesc + LessSizeOfPage
+                );
+    }
+  }
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cRead failed! p1=0x%x.\n",
+            __FUNCTION__, __LINE__, Status));
+    return Status;
+  }
+
+  crc16 = make_crc_checksum (
+            (UINT8 *) & (stMacDesc.MacLen),
+            sizeof (stMacDesc.MacLen) + sizeof (stMacDesc.Mac)
+          );
+  if ((crc16 != stMacDesc.Crc16) || (0 == crc16)) {
+    return EFI_NOT_FOUND;
+  }
+
+  for (i = 0; i < MAC_ADDR_LEN; i++) {
+    pucAddr[i] = stMacDesc.Mac[i];
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+OemSetMacE2prom (
+  IN UINT32 Port,
+  IN UINT8 *pucAddr
+  )
+{
+  I2C_DEVICE       stI2cDev = {0};
+  EFI_STATUS       Status;
+  UINT16           I2cOffset;
+  NIC_MAC_ADDRESS  stMacDesc = {0};
+  UINT32           i;
+  UINT16           RemainderMacOffset;
+  UINT16           LessSizeOfPage;
+
+  i = 0;
+  stMacDesc.MacLen = MAC_ADDR_LEN;
+
+  for (i = 0; i < MAC_ADDR_LEN; i++) {
+    stMacDesc.Mac[i] = pucAddr[i];
+  }
+
+  stMacDesc.Crc16 = make_crc_checksum (
+                      (UINT8 *) & (stMacDesc.MacLen),
+                      sizeof (stMacDesc.MacLen) + MAC_ADDR_LEN
+                    );
+
+  Status = I2CInit (0, EEPROM_I2C_PORT, Normal);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n",
+           __FUNCTION__, __LINE__, Status));
+    return Status;
+  }
+
+  I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS));
+
+  stI2cDev.DeviceType = DEVICE_TYPE_E2PROM;
+  stI2cDev.Port = EEPROM_I2C_PORT;
+  stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM;
+  stI2cDev.Socket = 0;
+  RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE;
+  LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset;
+  //The length of NIC_MAC_ADDRESS is 10 bytes long,
+  //It surly less than EEPROM page size, so we could
+  //code as bellow, check the address whether across the page boundary,
+  //and split the data when across page boundary.
+  if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) {
+    Status = I2CWrite (
+               &stI2cDev,
+               I2cOffset,
+               sizeof (NIC_MAC_ADDRESS),
+               (UINT8 *) &stMacDesc
+             );
+  } else {
+    Status = I2CWrite (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc);
+    if (!(EFI_ERROR (Status))) {
+      Status |= I2CWrite (
+                  &stI2cDev,
+                  I2cOffset + LessSizeOfPage,
+                  sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage,
+                  (UINT8 *) &stMacDesc + LessSizeOfPage
+                );
+    }
+  }
+  if (EFI_ERROR (Status))
+  {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cWrite failed! p1=0x%x.\n",
+            __FUNCTION__, __LINE__, Status));
+    return Status;
+  }
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+OemGetMac (
+  IN OUT EFI_MAC_ADDRESS *Mac,
+  IN     UINTN           Port
+  )
+{
+  EFI_STATUS Status;
+
+  if (NULL == Mac) {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n",
+            __FUNCTION__, __LINE__));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = OemGetMacE2prom (Port, Mac->Addr);
+  if ((EFI_ERROR (Status))) {
+    DEBUG ((DEBUG_ERROR,
+      "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n",
+      __FUNCTION__, __LINE__, Status));
+
+    Mac->Addr[0] = 0x00;
+    Mac->Addr[1] = 0x18;
+    Mac->Addr[2] = 0x82;
+    Mac->Addr[3] = 0x2F;
+    Mac->Addr[4] = 0x02;
+    Mac->Addr[5] = Port;
+    return EFI_SUCCESS;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+OemSetMac (
+  IN EFI_MAC_ADDRESS *Mac,
+  IN UINTN           Port
+  )
+{
+  EFI_STATUS Status;
+
+  if (NULL == Mac) {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n",
+            __FUNCTION__, __LINE__));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = OemSetMacE2prom (Port, Mac->Addr);
+  if ((EFI_ERROR (Status))) {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Set mac failed!\n", __FUNCTION__, __LINE__));
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+UINT32
+OemEthFindFirstSP (
+  VOID
+  )
+{
+  UINT32 i;
+
+  for (i = 0; i < ETH_MAX_PORT; i++) {
+    if (gEthPdtDesc[i].Valid == TRUE) {
+      return i;
+    }
+  }
+
+  return ETH_INVALID;
+}
+
+ETH_PRODUCT_DESC *
+OemEthInit (
+  UINT32 port
+  )
+{
+  return (ETH_PRODUCT_DESC *)(&(gEthPdtDesc[port]));
+}
+
+
+BOOLEAN
+OemIsInitEth (
+  UINT32 Port
+  )
+{
+  return TRUE;
+}
diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf
new file mode 100644
index 0000000000..ac849cb992
--- /dev/null
+++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf
@@ -0,0 +1,35 @@ 
+#/** @file
+#
+#    Copyright (c) 2018, Hisilicon Limited. All rights reserved.
+#    Copyright (c) 2017, 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]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = OemNicLib
+  FILE_GUID                      = 520F872C-FFCF-4EF3-AC01-85BDB0816DCE
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = OemNicLib
+
+[Sources.common]
+  OemNicLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ArmPkg/ArmPkg.dec
+  Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+  I2CLib
+  CpldIoLib