From cb0d4e5e8caefd9f62c676cb1084f3d22bc330d5 Mon Sep 17 00:00:00 2001 From: Ratan Gupta Date: Thu, 22 Dec 2016 19:05:57 +0530 Subject: Re-factor to use MRW and Inventory interfaces The write FRU command now figures out properties to be written for a FRU via a generated header file, which in turn is generated via scrips deriving their inputs from MRW and Inventory d-bus interfaces. Change-Id: I9939aeec24566cf518f4e63dc6ae344b236a541f Signed-off-by: Ratan Gupta --- frup.cpp | 98 +++++---------------------- frup.h | 79 ++++++++++++++++++---- writefrudata.cpp | 202 +++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 214 insertions(+), 165 deletions(-) diff --git a/frup.cpp b/frup.cpp index 1740f10..45d052b 100644 --- a/frup.cpp +++ b/frup.cpp @@ -46,9 +46,7 @@ #include #include #include - -#define uint8_t unsigned char -#define uint32_t unsigned int +#include "frup.h" #define TEXTSTR(a) #a # define ASSERT(x) \ @@ -110,61 +108,6 @@ typedef struct ipmi_fru_common_hdr uint8_t multirec; } __attribute__((packed)) ipmi_fru_common_hdr_t; -enum openbmc_vpd_key_id -{ - OPENBMC_VPD_KEY_CHASSIS_TYPE = 1, /* not a type/len */ - OPENBMC_VPD_KEY_CHASSIS_PART_NUM, - OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM, - OPENBMC_VPD_KEY_CHASSIS_CUSTOM1, - OPENBMC_VPD_KEY_CHASSIS_CUSTOM2, - OPENBMC_VPD_KEY_CHASSIS_CUSTOM3, - OPENBMC_VPD_KEY_CHASSIS_CUSTOM4, - OPENBMC_VPD_KEY_CHASSIS_CUSTOM5, - OPENBMC_VPD_KEY_CHASSIS_CUSTOM6, - OPENBMC_VPD_KEY_CHASSIS_CUSTOM7, - OPENBMC_VPD_KEY_CHASSIS_CUSTOM8, - OPENBMC_VPD_KEY_CHASSIS_MAX = OPENBMC_VPD_KEY_CHASSIS_CUSTOM8, - /* TODO: chassis_custom_fields */ - - OPENBMC_VPD_KEY_BOARD_MFG_DATE, /* not a type/len */ - OPENBMC_VPD_KEY_BOARD_MFR, - OPENBMC_VPD_KEY_BOARD_NAME, - OPENBMC_VPD_KEY_BOARD_SERIAL_NUM, - OPENBMC_VPD_KEY_BOARD_PART_NUM, - OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID, - OPENBMC_VPD_KEY_BOARD_CUSTOM1, - OPENBMC_VPD_KEY_BOARD_CUSTOM2, - OPENBMC_VPD_KEY_BOARD_CUSTOM3, - OPENBMC_VPD_KEY_BOARD_CUSTOM4, - OPENBMC_VPD_KEY_BOARD_CUSTOM5, - OPENBMC_VPD_KEY_BOARD_CUSTOM6, - OPENBMC_VPD_KEY_BOARD_CUSTOM7, - OPENBMC_VPD_KEY_BOARD_CUSTOM8, - OPENBMC_VPD_KEY_BOARD_MAX = OPENBMC_VPD_KEY_BOARD_CUSTOM8, - /* TODO: board_custom_fields */ - - OPENBMC_VPD_KEY_PRODUCT_MFR, - OPENBMC_VPD_KEY_PRODUCT_NAME, - OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM, - OPENBMC_VPD_KEY_PRODUCT_VER, - OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM, - OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG, - OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID, - OPENBMC_VPD_KEY_PRODUCT_CUSTOM1, - OPENBMC_VPD_KEY_PRODUCT_CUSTOM2, - OPENBMC_VPD_KEY_PRODUCT_CUSTOM3, - OPENBMC_VPD_KEY_PRODUCT_CUSTOM4, - OPENBMC_VPD_KEY_PRODUCT_CUSTOM5, - OPENBMC_VPD_KEY_PRODUCT_CUSTOM6, - OPENBMC_VPD_KEY_PRODUCT_CUSTOM7, - OPENBMC_VPD_KEY_PRODUCT_CUSTOM8, - OPENBMC_VPD_KEY_PRODUCT_MAX = OPENBMC_VPD_KEY_PRODUCT_CUSTOM8, - - OPENBMC_VPD_KEY_MAX, - OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX=8, - -}; - const char* vpd_key_names [] = { "Key Names Table Start", @@ -791,7 +734,7 @@ void _append_to_dict (uint8_t vpd_key_id, uint8_t* vpd_key_val, sd_bus_message* char *bin_in_ascii = (char *)malloc(bin_in_ascii_len); /* For reading byte from the area */ - size_t val = 0; + int val = 0; char *bin_copy = &((char *)bin_in_ascii)[2]; @@ -986,11 +929,11 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl) return (rv); } -int parse_fru_area (const uint8_t area, const void* msgbuf, const size_t len, sd_bus_message* vpdtbl) +int parse_fru_area (const uint8_t area, const void* msgbuf, + const size_t len, IPMIFruInfo& info) { int rv = -1; int i = 0; - int sdr = 0; /* Chassis */ uint8_t chassis_type; @@ -1008,7 +951,6 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const size_t len, sd //uint8_t* hdr = NULL; ASSERT (msgbuf); - ASSERT (vpdtbl); for (i=0; i + (vpd_info[i].type_length_field))); - _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl); -/* - ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1; - sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str); -*/ } break; case IPMI_FRU_AREA_BOARD_INFO: @@ -1074,21 +1015,14 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const size_t len, sd #if IPMI_FRU_PARSER_DEBUG printf ("Board : Appending [%s] = [%d]\n", vpd_key_names[i], timestr); #endif - sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", timestr); - if (sdr < 0) - { -#if IPMI_FRU_PARSER_DEBUG - printf ("ipmi_fru_board_info_area : sd_bus_message_append Failed [ %d ] for [%s]\n", sdr, vpd_key_names[i]); -#endif - } + info[i] = std::make_pair(vpd_key_names[i], + std::string(timestr)); continue; } + info[i] = std::make_pair(vpd_key_names[i], + std::string(reinterpret_cast + (vpd_info[i].type_length_field))); - _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl); -/* - ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1; - sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str); -*/ } break; case IPMI_FRU_AREA_PRODUCT_INFO: @@ -1110,7 +1044,9 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const size_t len, sd for (i=OPENBMC_VPD_KEY_PRODUCT_MFR; i<=OPENBMC_VPD_KEY_PRODUCT_MAX; i++) { - _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl); + info[i] = std::make_pair(vpd_key_names[i], + std::string(reinterpret_cast + (vpd_info[i].type_length_field))); } break; default: diff --git a/frup.h b/frup.h index 64a0562..ca5fa96 100644 --- a/frup.h +++ b/frup.h @@ -2,19 +2,8 @@ #define OPENBMC_IPMI_FRU_PARSER_H #include +#include -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Parse an IPMI write fru data message into a dictionary containing name value pair of VPD entries.*/ -int parse_fru (const void* msgbuf, sd_bus_message* vpdtbl); -int parse_fru_area (const uint8_t area, const void* msgbuf, const size_t len, sd_bus_message* vpdtbl); - -#ifdef __cplusplus -} -#endif enum ipmi_fru_area_type { @@ -26,4 +15,70 @@ enum ipmi_fru_area_type IPMI_FRU_AREA_TYPE_MAX }; + +enum openbmc_vpd_key_id +{ + OPENBMC_VPD_KEY_CHASSIS_TYPE = 1, /* not a type/len */ + OPENBMC_VPD_KEY_CHASSIS_PART_NUM, + OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM, + OPENBMC_VPD_KEY_CHASSIS_CUSTOM1, + OPENBMC_VPD_KEY_CHASSIS_CUSTOM2, + OPENBMC_VPD_KEY_CHASSIS_CUSTOM3, + OPENBMC_VPD_KEY_CHASSIS_CUSTOM4, + OPENBMC_VPD_KEY_CHASSIS_CUSTOM5, + OPENBMC_VPD_KEY_CHASSIS_CUSTOM6, + OPENBMC_VPD_KEY_CHASSIS_CUSTOM7, + OPENBMC_VPD_KEY_CHASSIS_CUSTOM8, + OPENBMC_VPD_KEY_CHASSIS_MAX = OPENBMC_VPD_KEY_CHASSIS_CUSTOM8, + /* TODO: chassis_custom_fields */ + + OPENBMC_VPD_KEY_BOARD_MFG_DATE, /* not a type/len */ + OPENBMC_VPD_KEY_BOARD_MFR, + OPENBMC_VPD_KEY_BOARD_NAME, + OPENBMC_VPD_KEY_BOARD_SERIAL_NUM, + OPENBMC_VPD_KEY_BOARD_PART_NUM, + OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID, + OPENBMC_VPD_KEY_BOARD_CUSTOM1, + OPENBMC_VPD_KEY_BOARD_CUSTOM2, + OPENBMC_VPD_KEY_BOARD_CUSTOM3, + OPENBMC_VPD_KEY_BOARD_CUSTOM4, + OPENBMC_VPD_KEY_BOARD_CUSTOM5, + OPENBMC_VPD_KEY_BOARD_CUSTOM6, + OPENBMC_VPD_KEY_BOARD_CUSTOM7, + OPENBMC_VPD_KEY_BOARD_CUSTOM8, + OPENBMC_VPD_KEY_BOARD_MAX = OPENBMC_VPD_KEY_BOARD_CUSTOM8, + /* TODO: board_custom_fields */ + + OPENBMC_VPD_KEY_PRODUCT_MFR, + OPENBMC_VPD_KEY_PRODUCT_NAME, + OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM, + OPENBMC_VPD_KEY_PRODUCT_VER, + OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM, + OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG, + OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID, + OPENBMC_VPD_KEY_PRODUCT_CUSTOM1, + OPENBMC_VPD_KEY_PRODUCT_CUSTOM2, + OPENBMC_VPD_KEY_PRODUCT_CUSTOM3, + OPENBMC_VPD_KEY_PRODUCT_CUSTOM4, + OPENBMC_VPD_KEY_PRODUCT_CUSTOM5, + OPENBMC_VPD_KEY_PRODUCT_CUSTOM6, + OPENBMC_VPD_KEY_PRODUCT_CUSTOM7, + OPENBMC_VPD_KEY_PRODUCT_CUSTOM8, + OPENBMC_VPD_KEY_PRODUCT_MAX = OPENBMC_VPD_KEY_PRODUCT_CUSTOM8, + + OPENBMC_VPD_KEY_MAX, + OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX=8, + +}; + +using IPMIFruInfo = std::array, + OPENBMC_VPD_KEY_MAX>; + + +/* Parse an IPMI write fru data message into a dictionary containing name value pair of VPD entries.*/ +int parse_fru (const void* msgbuf, sd_bus_message* vpdtbl); + +int parse_fru_area (const uint8_t area, const void* msgbuf, + const size_t len, IPMIFruInfo& info); + #endif diff --git a/writefrudata.cpp b/writefrudata.cpp index 3619966..3e09bc8 100644 --- a/writefrudata.cpp +++ b/writefrudata.cpp @@ -14,11 +14,22 @@ #include #include "frup.h" #include "fru-area.hpp" +#include "fru-gen.hpp" // OpenBMC System Manager dbus framework const char *sys_object_name = "/org/openbmc/managers/System"; const char *sys_intf_name = "org.openbmc.managers.System"; +extern const FruMap frus; + +// Association between interface and the dbus property +using InterfaceList = std::map>; + +// Association between property and its value +using PropertiesList = std::map; + + //---------------------------------------------------------------- // Constructor //---------------------------------------------------------------- @@ -343,98 +354,145 @@ int verify_fru_data(const uint8_t *data, const size_t len) } //------------------------------------------------------------------------ -// Takes FRU data, invokes Parser for each fru record area and updates -// Inventory +// Gets the value of the key from the fru dictionary of the given section. +// FRU dictionary is parsed fru data for all the sections. //------------------------------------------------------------------------ -int ipmi_update_inventory(fru_area_vec_t & area_vec) + +std::string getFRUValue(const std::string& section, + const std::string& key, + IPMIFruInfo& fruData) { - // Generic error reporter - int rc = 0; - // Dictionary object to hold Name:Value pair - sd_bus_message *fru_dict = NULL; + auto minIndexValue = 0; + auto maxIndexValue = 0; + std::string fruValue = ""; + if (section == "Board") + { + minIndexValue = OPENBMC_VPD_KEY_BOARD_MFG_DATE; + maxIndexValue = OPENBMC_VPD_KEY_BOARD_MAX; + } + else if (section == "Product") + { + minIndexValue = OPENBMC_VPD_KEY_PRODUCT_MFR; + maxIndexValue = OPENBMC_VPD_KEY_PRODUCT_MAX; - // SD Bus error report mechanism. - sd_bus_error bus_error = SD_BUS_ERROR_NULL; + } + else if (section == "Chassis") + { + minIndexValue = OPENBMC_VPD_KEY_CHASSIS_TYPE; + maxIndexValue = OPENBMC_VPD_KEY_CHASSIS_MAX; + } - // Response from sd bus calls - sd_bus_message *response = NULL; + auto first = fruData.cbegin() + minIndexValue; + auto last = first + (maxIndexValue - minIndexValue) + 1; - // For each FRU area, extract the needed data , get it parsed and update - // the Inventory. - for(auto& iter : area_vec) + auto itr = std::find_if(first, last, + [&key](auto& e){ return key == e.first; }); + + if (itr != last) { - // Start fresh on each. - sd_bus_error_free(&bus_error); - sd_bus_message_unref(response); - sd_bus_message_unref(fru_dict); - - // Constructor to allow further initializations and customization. - rc = sd_bus_message_new_method_call((iter)->get_bus_type(), - &fru_dict, - (iter)->get_bus_name(), - (iter)->get_obj_path(), - (iter)->get_intf_name(), - "update"); - if(rc < 0) - { - fprintf(stderr,"ERROR: creating a update method call for bus_name:[%s]\n", - (iter)->get_bus_name()); - break; - } + fruValue = itr->second; + } + return fruValue; - // A Dictionary ({}) having (string, variant) - rc = sd_bus_message_open_container(fru_dict, 'a', "{sv}"); - if(rc < 0) +} + +// TODO: Remove once the call to inventory manager is added +auto print = [](const InterfaceList& object, const std::string& path) +{ + std::cout << "\n"; + std::cout << path << "\n"; + std::cout << "\n"; + for(const auto& o : object) + { + std::cout << o.first << "\n"; + for(const auto& i : o.second) { - fprintf(stderr,"ERROR:[%d] creating a dict container:\n",errno); - break; + std::cout << i.first << " : " << i.second << "\n"; } + std::cout << "\n"; + } +}; +//------------------------------------------------------------------------ +// Takes FRU data, invokes Parser for each fru record area and updates +// Inventory +//------------------------------------------------------------------------ +int ipmi_update_inventory(fru_area_vec_t& area_vec) +{ + // Generic error reporter + int rc = 0; + uint8_t fruid = 0; + IPMIFruInfo fruData; + + // For each FRU area, extract the needed data , get it parsed and update + // the Inventory. + for (const auto& fruArea : area_vec) + { + fruid = fruArea->get_fruid(); // Fill the container with information - rc = parse_fru_area((iter)->get_type(), (void *)(iter)->get_data(), (iter)->get_len(), fru_dict); - if(rc < 0) + rc = parse_fru_area((fruArea)->get_type(), (void*)(fruArea)->get_data(), + (fruArea)->get_len(), fruData); + if (rc < 0) { - fprintf(stderr,"ERROR parsing FRU records\n"); - break; + std::cerr << "ERROR parsing FRU records\n"; + return rc; } + } // END walking the vector of areas and updating - sd_bus_message_close_container(fru_dict); + // For each Fru we have the list of instances which needs to be updated. + // Each instance object implements certain interfaces. + // Each Interface is having Dbus properties. + // Each Dbus Property would be having metaData(eg section,VpdPropertyName). - // Now, Make the actual call to update the FRU inventory database with the - // dictionary given by FRU Parser. There is no response message expected for - // this. - rc = sd_bus_call((iter)->get_bus_type(), // On the System Bus - fru_dict, // With the Name:value dictionary array - 0, // - &bus_error, // Object to return error. - &response); // Response message if any. + // Here we are just printing the object,interface and the properties. + // which needs to be called with the new inventory manager implementation. + // TODO:- Call the new Inventory Manager. + auto iter = frus.find(fruid); + if (iter == frus.end()) + { + std::cerr << "ERROR Unable to get the fru info for FRU=" << fruid << "\n"; + return -1; + } + auto& instanceList = iter->second; - if(rc < 0) - { - fprintf(stderr, "ERROR:[%s] updating FRU inventory for ID:[0x%X]\n", - bus_error.message, (iter)->get_fruid()); - break; - } - else if((iter)->is_bmc_fru()) - { - // For FRUs that are accessible by HostBoot, host boot does all of - // these. - printf("SUCCESS: Updated:[%s_%d] successfully. Setting Valid bit\n", - (iter)->get_name(), (iter)->get_fruid()); + if (instanceList.size() <= 0) + { + std::cout << "Object List empty for this FRU=" << fruid << "\n"; + } + for (auto& instance : instanceList) + { + InterfaceList interfaces; - (iter)->set_valid(true); - } - else + for (auto& interfaceList : instance.second) { - printf("SUCCESS: Updated:[%s_%d] successfully\n", - (iter)->get_name(), (iter)->get_fruid()); - } - } // END walking the vector of areas and updating + PropertiesList prop;//store all the properties + for (auto& properties : interfaceList.second) + { + std::string section, property, value; + for (auto& info : properties.second) + { + if (info.first == "IPMIFruSection") + { + section = std::move(info.second); + } + if (info.first == "IPMIFruProperty") + { + property = std::move(info.second); + } + } - sd_bus_error_free(&bus_error); - sd_bus_message_unref(response); - sd_bus_message_unref(fru_dict); + if (!section.empty() && !property.empty()) + { + value = getFRUValue(section, property, fruData); + } + prop.emplace(std::move(properties.first), std::move(value)); + } + interfaces.emplace(std::move(interfaceList.first), std::move(prop)); + } + //TODO:- remove it later with the inventory manager call. + print(interfaces, instance.first); + } return rc; } -- cgit v1.2.1