summaryrefslogtreecommitdiffstats
path: root/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c
blob: f3ad36ec3a2fb6ad14b3bc0008cfd96db2279b62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/** @file
  RedfishSmbiosHostInterface.c

  Discover Redfish SMBIOS Host Interface.

  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>

  SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include "RedfishDiscoverInternal.h"

SMBIOS_TABLE_TYPE42  *mType42Record;

/**
  The function gets information reported in Redfish Host Interface.

  It simply frees the packet.

  @param[in]  Smbios           SMBIOS protocol.
  @param[out] DeviceDescriptor Pointer to REDFISH_INTERFACE_DATA.
  @param[out] ProtocolData     Pointer to REDFISH_OVER_IP_PROTOCOL_DATA.

  @retval EFI_SUCCESS    Get host interface succesfully.
  @retval Otherwise      Fail to tet host interface.

**/
EFI_STATUS
RedfishGetHostInterfaceProtocolData (
  IN EFI_SMBIOS_PROTOCOL              *Smbios,
  OUT REDFISH_INTERFACE_DATA          **DeviceDescriptor,
  OUT REDFISH_OVER_IP_PROTOCOL_DATA   **ProtocolData
  )
{
  EFI_STATUS                        Status;
  EFI_SMBIOS_HANDLE                 SmbiosHandle;
  EFI_SMBIOS_TABLE_HEADER           *Record;
  UINT16                            Offset;
  UINT8                             *RecordTmp;
  UINT8                             ProtocolLength;
  UINT8                             SpecificDataLen;

  if ((Smbios == NULL) || (ProtocolData == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
  Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
  while (!EFI_ERROR (Status) && SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED) {
    if (Record->Type == SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE) {
      //
      // Check Interface Type, should be Network Host Interface = 40h
      //
      mType42Record = (SMBIOS_TABLE_TYPE42 *) Record;
      if (mType42Record->InterfaceType == MCHostInterfaceTypeNetworkHostInterface) {
        ASSERT (Record->Length >= 9);
        Offset = 5;
        RecordTmp = (UINT8 *) Record + Offset;
        //
        // Get interface specific data length.
        //
        SpecificDataLen = *RecordTmp;
        Offset += 1;
        RecordTmp = (UINT8 *) Record + Offset;

        //
        // Check Device Type, only PCI/PCIe Network Interface v2 is supported now.
        //
        if (*RecordTmp == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) {
          ASSERT (SpecificDataLen == sizeof (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2) + 1);
          *DeviceDescriptor = (REDFISH_INTERFACE_DATA *)RecordTmp;
          Offset = Offset + SpecificDataLen;
          RecordTmp = (UINT8 *) Record + Offset;
          //
          // Check Protocol count. if > 1, only use the first protocol.
          //
          ASSERT (*RecordTmp == 1);
          Offset += 1;
          RecordTmp = (UINT8 *) Record + Offset;
          //
          // Check protocol identifier.
          //
          if (*RecordTmp == MCHostInterfaceProtocolTypeRedfishOverIP) {
            Offset += 1;
            RecordTmp = (UINT8 *) Record + Offset;
            ProtocolLength = *RecordTmp;

            Offset += 1;
            RecordTmp = (UINT8 *) Record + Offset;

            //
            // This SMBIOS record is invalid, if the length of protocol specific data for
            // Redfish Over IP protocol is wrong.
            //
            if ((*(RecordTmp + 90) + sizeof (REDFISH_OVER_IP_PROTOCOL_DATA) - 1) != ProtocolLength) {
              return EFI_SECURITY_VIOLATION;
            }

            Offset += ProtocolLength;
            //
            // This SMBIOS record is invalid, if the length is smaller than the offset.
            //
            if (Offset > mType42Record->Hdr.Length) {
              return EFI_SECURITY_VIOLATION;
            }
            *ProtocolData = (REDFISH_OVER_IP_PROTOCOL_DATA *)RecordTmp;
            return EFI_SUCCESS;
          }
        }
      }
    }
    Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
  }

  *ProtocolData = NULL;
  return EFI_NOT_FOUND;
}