Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 48 additions & 10 deletions common/dev/cx7.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@
(uint8_t *)&req, req_len, resp_buf, sizeof(resp_buf));

if (resp_len == 0) {
LOG_ERR("Failed to get CX7 sensor #%d reading", init_arg->sensor_id);

LOG_INF("Attempting to re-initialize EID 0x%x for CX7 device due to sensor read failure",
mctp_dest_eid);
LOG_ERR("Failed to get sensor num 0x%x CX7 sensor #%x reading", cfg->num,
init_arg->sensor_id);

if (init_arg->re_init_eid_fn) {
LOG_INF("Attempting to re-initialize EID 0x%x for CX7 device due to sensor read failure",
mctp_dest_eid);
init_arg->re_init_eid_fn();
}

Expand All @@ -75,14 +75,18 @@
sizeof(resp_buf));

if (resp_len == 0) {
LOG_ERR("Failed to get CX7 sensor #%d reading after EID re-initialization",
init_arg->sensor_id);
LOG_ERR("Failed to get sensor num 0x%x CX7 sensor #%d reading after EID re-initialization",
cfg->num, init_arg->sensor_id);
return SENSOR_FAIL_TO_ACCESS;
}
}

struct pldm_get_sensor_reading_resp *res = (struct pldm_get_sensor_reading_resp *)resp_buf;

LOG_DBG("sensor num 0x%x, CX7 sensor 0x%x reading response - completion_code: 0x%x, sensor_operational_state: 0x%x, sensor_data_size: 0x%x \n",
cfg->num, init_arg->sensor_id, res->completion_code, res->sensor_operational_state,
res->sensor_data_size);

if ((res->completion_code != PLDM_SUCCESS)) {
LOG_ERR("Failed to get get sensor reading, completion_code = 0x%x",
res->completion_code);
Expand All @@ -91,20 +95,54 @@

sensor_val *sval = (sensor_val *)reading;
if (res->sensor_operational_state == PLDM_SENSOR_ENABLED) {
if (res->sensor_data_size != PLDM_SENSOR_DATA_SIZE_SINT16) {
switch (res->sensor_data_size) {
case PLDM_SENSOR_DATA_SIZE_UINT8:
sval->integer = res->present_reading[0];
sval->fraction = 0;
return SENSOR_READ_SUCCESS;

case PLDM_SENSOR_DATA_SIZE_SINT8:
sval->integer = (int8_t)res->present_reading[0];
sval->fraction = 0;
return SENSOR_READ_SUCCESS;

case PLDM_SENSOR_DATA_SIZE_UINT16:
sval->integer = (res->present_reading[1] << 8) | res->present_reading[0];
sval->fraction = 0;
return SENSOR_READ_SUCCESS;
} else if (res->sensor_data_size != PLDM_SENSOR_DATA_SIZE_SINT8) {
sval->integer = res->present_reading[0];

case PLDM_SENSOR_DATA_SIZE_SINT16:
sval->integer =
(int16_t)((res->present_reading[1] << 8) | res->present_reading[0]);
sval->fraction = 0;
return SENSOR_READ_SUCCESS;

case PLDM_SENSOR_DATA_SIZE_UINT32:
sval->integer = (res->present_reading[3] << 24) |
(res->present_reading[2] << 16) |
(res->present_reading[1] << 8) | res->present_reading[0];
sval->fraction = 0;
return SENSOR_READ_SUCCESS;

case PLDM_SENSOR_DATA_SIZE_SINT32:
sval->integer =
(int32_t)((res->present_reading[3] << 24) |
(res->present_reading[2] << 16) |
(res->present_reading[1] << 8) | res->present_reading[0]);
sval->fraction = 0;
return SENSOR_READ_SUCCESS;

LOG_DBG("CX7 sensor reading: %d.%d", sval->integer, sval->fraction);

Check failure on line 135 in common/dev/cx7.c

View workflow job for this annotation

GitHub Actions / Aggregate-Lint-Output

[] reported by reviewdog 🐶 Statements following 'return' will never be executed. Raw Output: common/dev/cx7.c:135:4:Statements following 'return' will never be executed.

default:
LOG_ERR("Unsupported sensor data size: 0x%x", res->sensor_data_size);
return SENSOR_FAIL_TO_ACCESS;
}
} else if (res->sensor_operational_state == PLDM_SENSOR_UNAVAILABLE) {
return SENSOR_UNAVAILABLE;
}

LOG_ERR("CX7 Failed to get get sensor reading, sensor operational state=0x%x",
LOG_ERR("CX7 Failed to get sensor reading, sensor operational state=0x%x",
res->sensor_operational_state);
return SENSOR_FAIL_TO_ACCESS;
}
Expand Down
22 changes: 22 additions & 0 deletions common/dev/include/cx7.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef CX7_H
#define CX7_H

uint8_t cx7_init(sensor_cfg *cfg);

#endif
183 changes: 182 additions & 1 deletion meta-facebook/gt-cc/src/platform/plat_fru.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@ static bool get_nic_product_manufacturer(uint8_t fru_id, char *manufacturer,
return false;
}

// Validate FRU ID before accessing fru_config array
if (fru_id >= MAX_FRU_ID) {
LOG_ERR("Invalid FRU ID %d (MAX: %d)", fru_id, MAX_FRU_ID);
return false;
}

EEPROM_ENTRY fru_entry;
memset(&fru_entry, 0, sizeof(fru_entry));

Expand Down Expand Up @@ -338,10 +344,185 @@ static bool get_nic_product_manufacturer(uint8_t fru_id, char *manufacturer,

decode_field(fru_entry.data, field_len, manufacturer, manufacturer_size);

LOG_DBG("NIC FRU ID %d product manufacturer: %s", fru_id, manufacturer);
LOG_INF("NIC FRU ID %d product manufacturer: %s", fru_id, manufacturer);
return true;
}

static bool get_nic_product_name(uint8_t fru_id, char *name, uint8_t name_size)
{
CHECK_NULL_ARG_WITH_RETURN(name, false);

if (name_size == 0) {
LOG_ERR("Invalid name size: %d", name_size);
return false;
}

// Validate FRU ID before accessing fru_config array
if (fru_id >= MAX_FRU_ID) {
LOG_ERR("Invalid FRU ID %d (MAX: %d)", fru_id, MAX_FRU_ID);
return false;
}

EEPROM_ENTRY fru_entry;
memset(&fru_entry, 0, sizeof(fru_entry));

fru_entry.config = fru_config[fru_id];
fru_entry.offset = 0;
fru_entry.data_len = 8;

if (FRU_read(&fru_entry) != FRU_READ_SUCCESS) {
LOG_ERR("Failed to read FRU header for FRU ID %d", fru_id);
return false;
}

// Check FRU common header format identifier
if (fru_entry.data[0] != 0x01) {
LOG_ERR("Invalid FRU format for FRU ID %d", fru_id);
return false;
}

// Get product area offset (5th byte * 8)
uint16_t product_area_offset = fru_entry.data[4] * 8;
if (product_area_offset == 0) {
LOG_ERR("No product area found for FRU ID %d", fru_id);
return false;
}

// Read product area header (format, length, language)
fru_entry.offset = product_area_offset;
fru_entry.data_len = 3;

if (FRU_read(&fru_entry) != FRU_READ_SUCCESS) {
LOG_ERR("Failed to read product area header for FRU ID %d", fru_id);
return false;
}

// Check product area format version
if (fru_entry.data[0] != 0x01) {
LOG_ERR("Invalid product area format for FRU ID %d", fru_id);
return false;
}

uint16_t area_len = fru_entry.data[1] * 8;
if (area_len < 5) {
LOG_ERR("Product area too short for FRU ID %d", fru_id);
return false;
}

// Read Field 1 (product manufacturer) type/length byte at offset+3
fru_entry.offset = product_area_offset + 3;
fru_entry.data_len = 1;

if (FRU_read(&fru_entry) != FRU_READ_SUCCESS) {
LOG_ERR("Failed to read product manufacturer type/length for FRU ID %d", fru_id);
return false;
}

uint8_t mfr_type_length = fru_entry.data[0];
if (mfr_type_length == 0xC1) {
LOG_WRN("No product manufacturer field for FRU ID %d, cannot reach product name",
fru_id);
return false;
}

int mfr_len = mfr_type_length & 0x3F;
// Bounds check: manufacturer field must not exceed the area
if ((3 + 1 + mfr_len + 1) > area_len) {
LOG_ERR("Manufacturer field overflows product area for FRU ID %d", fru_id);
return false;
}

// Field 2 (product name) type/length byte is right after manufacturer data
uint16_t name_tl_offset = product_area_offset + 3 + 1 + mfr_len;
fru_entry.offset = name_tl_offset;
fru_entry.data_len = 1;

if (FRU_read(&fru_entry) != FRU_READ_SUCCESS) {
LOG_ERR("Failed to read product name type/length for FRU ID %d", fru_id);
return false;
}

uint8_t name_type_length = fru_entry.data[0];
if (name_type_length == 0xC1) {
LOG_WRN("No product name field found for FRU ID %d", fru_id);
return false;
}

int field_len = name_type_length & 0x3F;
if (field_len <= 0) {
LOG_WRN("Product name field is empty for FRU ID %d", fru_id);
return false;
}

// Cap read length to fit in caller's buffer (leave room for NUL terminator)
int read_len = (field_len < (name_size - 1)) ? field_len : (name_size - 1);

// Bounds check: product name field must not exceed the area
if ((name_tl_offset - product_area_offset + 1 + read_len) > area_len) {
LOG_ERR("Product name field overflows product area for FRU ID %d", fru_id);
return false;
}

// Read the product name field data
fru_entry.offset = name_tl_offset + 1;
fru_entry.data_len = read_len;

if (FRU_read(&fru_entry) != FRU_READ_SUCCESS) {
LOG_ERR("Failed to read product name data for FRU ID %d", fru_id);
return false;
}

decode_field(fru_entry.data, read_len, name, name_size);

LOG_INF("NIC FRU ID %d product name: %s", fru_id, name);
return true;
}

bool get_first_nic_name(char *name, uint8_t name_size)
{
CHECK_NULL_ARG_WITH_RETURN(name, false);

if (name_size == 0) {
LOG_ERR("Invalid name size: %d", name_size);
return false;
}

bool found_name = false;
char temp_name[32];

for (uint8_t i = 0; i < NIC_MAX_NUMBER; i++) {
// Validate FRU ID before use to prevent accessing invalid memory
uint8_t fru_id = NIC0_FRU_ID + i;
if (fru_id >= MAX_FRU_ID) {
LOG_ERR("Invalid FRU ID %d for NIC%d, skipping", fru_id, i);
continue;
}

// Check if NIC is present (presence pin is active low)
if (gpio_get(nic_prsnt_pin[i])) {
LOG_INF("NIC%d: Not present", i);
continue;
}

if (get_nic_product_name(fru_id, temp_name, sizeof(temp_name))) {
LOG_INF("NIC%d: Product Name = %s", i, temp_name);

// Found the first name, save it and return immediately
// Use the smaller of the two buffer sizes to prevent overflow
uint8_t copy_size =
(sizeof(temp_name) < name_size) ? sizeof(temp_name) : name_size;
strncpy(name, temp_name, copy_size - 1);
name[copy_size - 1] = '\0';
found_name = true;
break;
} else {
LOG_INF("NIC%d: Failed to read product name", i);
}
}

return found_name;
}

bool get_first_nic_manufacturer(char *manufacturer, uint8_t manufacturer_size)
{
CHECK_NULL_ARG_WITH_RETURN(manufacturer, false);
Expand Down
2 changes: 2 additions & 0 deletions meta-facebook/gt-cc/src/platform/plat_fru.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum GT_NIC_CONFIG {
NIC_CONFIG_IB_CX7 = 2,
NIC_CONFIG_THOR2 = 3,
NIC_CONFIG_POLLARA = 4,
NIC_CONFIG_VULCANO = 5,
};

#define FRU_CFG_NUM MAX_FRU_ID
Expand Down Expand Up @@ -73,5 +74,6 @@ typedef struct {

uint8_t check_nic_type_by_fru();
bool get_first_nic_manufacturer(char *manufacturer, uint8_t manufacturer_size);
bool get_first_nic_name(char *name, uint8_t name_size);

#endif
Loading
Loading