//------------------------------------------------------------------------ // 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; // Dictionary object to hold Name:Value pair sd_bus_message *fru_dict = NULL; // SD Bus error report mechanism. sd_bus_error bus_error = SD_BUS_ERROR_NULL; // Response from sd bus calls sd_bus_message *response = NULL; // For each FRU area, extract the needed data , get it parsed and update // the Inventory. for(auto& iter : area_vec) { // 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; } // A Dictionary ({}) having (string, variant) rc = sd_bus_message_open_container(fru_dict, 'a', "{sv}"); if(rc < 0) { fprintf(stderr,"ERROR:[%d] creating a dict container:\n",errno); break; } // Fill the container with information rc = parse_fru_area((iter)->get_type(), (void *)(iter)->get_data(), (iter)->get_len(), fru_dict); if(rc < 0) { fprintf(stderr,"ERROR parsing FRU records\n"); break; } sd_bus_message_close_container(fru_dict); // 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. 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()); (iter)->set_valid(true); } else { printf("SUCCESS: Updated:[%s_%d] successfully\n", (iter)->get_name(), (iter)->get_fruid()); } } // END walking the vector of areas and updating sd_bus_error_free(&bus_error); sd_bus_message_unref(response); sd_bus_message_unref(fru_dict); return rc; }
//------------------------------------------------------------------------ // Takes FRU data, invokes Parser for each fru record area and updates // Inventory //------------------------------------------------------------------------ int ipmi_update_inventory(const uint8_t fruid, const uint8_t *fru_data, fru_area_vec_t & area_vec) { // Now, use this fru dictionary object and connect with FRU Inventory Dbus // and update the data for this FRU ID. int rc = 0; // Dictionary object to hold Name:Value pair sd_bus_message *fru_dict = NULL; // SD Bus error report mechanism. sd_bus_error bus_error = SD_BUS_ERROR_NULL; // Gets a hook onto either a SYSTEM or SESSION bus sd_bus *bus_type = ipmid_get_sd_bus_connection(); // Req message contains the specifics about which method etc that we want to // access on which bus, object sd_bus_message *response = NULL; // For each FRU area, extract the needed data , get it parsed and update // the Inventory. for(auto& iter : area_vec) { uint8_t area_type = (iter).type; uint8_t area_data[(iter).len]; memset(area_data, 0x0, sizeof(area_data)); // Grab area specific data memmove(area_data, (iter).offset, (iter).len); // Need this to get respective DBUS objects const char *area_name = NULL; if(area_type == IPMI_FRU_AREA_CHASSIS_INFO) { area_name = "CHASSIS_"; } else if(area_type == IPMI_FRU_AREA_BOARD_INFO) { area_name = "BOARD_"; } else if(area_type == IPMI_FRU_AREA_PRODUCT_INFO) { area_name = "PRODUCT_"; } else { fprintf(stderr, "ERROR: Invalid Area type :[%d]",area_type); break; } // What we need is BOARD_1, PRODUCT_1, CHASSIS_1 etc.. char fru_area_name[16] = {0}; sprintf(fru_area_name,"%s%d",area_name, fruid); #ifdef __IPMI_DEBUG__ printf("Updating Inventory with :[%s]\n",fru_area_name); #endif // Each area needs a clean set. sd_bus_error_free(&bus_error); sd_bus_message_unref(response); sd_bus_message_unref(fru_dict); // We want to call a method "getObjectFromId" on System Bus that is // made available over OpenBmc system services. rc = sd_bus_call_method(bus_type, // On the System Bus bus_name, // Service to contact object_name, // Object path intf_name, // Interface name "getObjectFromId", // Method to be called &bus_error, // object to return error &response, // Response message on success "ss", // input message (string,byte) "FRU_STR", // First argument to getObjectFromId fru_area_name); // Second Argument if(rc < 0) { fprintf(stderr, "Failed to issue method call: %s\n", bus_error.message); break; } // Method getObjectFromId returns 3 parameters and all are strings, namely // bus_name , object_path and interface name for accessing that particular // FRU over Inventory SDBUS manager. 'sss' here mentions that format. char *inv_bus_name, *inv_obj_path, *inv_intf_name; rc = sd_bus_message_read(response, "(sss)", &inv_bus_name, &inv_obj_path, &inv_intf_name); if(rc < 0) { fprintf(stderr, "Failed to parse response message:[%s]\n", strerror(-rc)); break; } #ifdef __IPMI_DEBUG__ printf("fru_area=[%s], inv_bus_name=[%s], inv_obj_path=[%s],inv_intf_name=[%s]\n", fru_area_name, inv_bus_name, inv_obj_path, inv_intf_name); #endif // Constructor to allow further initializations and customization. rc = sd_bus_message_new_method_call(bus_type, &fru_dict, inv_bus_name, inv_obj_path, inv_intf_name, "update"); if(rc < 0) { fprintf(stderr,"ERROR: creating a update method call\n"); break; } // A Dictionary ({}) having (string, variant) rc = sd_bus_message_open_container(fru_dict, 'a', "{sv}"); if(rc < 0) { fprintf(stderr,"ERROR:[%d] creating a dict container:\n",errno); break; } // Fill the container with information rc = parse_fru_area((iter).type, (void *)area_data, (iter).len, fru_dict); if(rc < 0) { fprintf(stderr,"ERROR parsing FRU records\n"); break; } sd_bus_message_close_container(fru_dict); // 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(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. if(rc < 0) { fprintf(stderr, "ERROR:[%s] updating FRU inventory for ID:[0x%X]\n", bus_error.message, fruid); } else { printf("SUCCESS: Updated:[%s] successfully\n",fru_area_name); } } // END walking the vector of areas and updating sd_bus_error_free(&bus_error); sd_bus_message_unref(response); sd_bus_message_unref(fru_dict); sd_bus_unref(bus_type); return rc; }