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 --- writefrudata.cpp | 202 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 130 insertions(+), 72 deletions(-) (limited to 'writefrudata.cpp') 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