1 /* 2 * Copyright (c) 2018 Intel Corporation. 3 * Copyright (c) 2018-present Facebook. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include <ipmid/api.h> 19 20 #include <sys/stat.h> 21 #include <fcntl.h> 22 #include <unistd.h> 23 #include <commandutils.hpp> 24 #include <iostream> 25 #include <phosphor-logging/log.hpp> 26 #include <sdbusplus/message/types.hpp> 27 #include <appcommands.hpp> 28 29 namespace ipmi 30 { 31 32 static void registerAPPFunctions() __attribute__((constructor)); 33 static constexpr size_t GUID_SIZE = 16; 34 // TODO Make offset and location runtime configurable to ensure we 35 // can make each define their own locations. 36 static constexpr off_t OFFSET_SYS_GUID = 0x17F0; 37 static constexpr off_t OFFSET_DEV_GUID = 0x1800; 38 static constexpr const char *FRU_EEPROM = "/sys/bus/i2c/devices/6-0054/eeprom"; 39 static uint8_t globEna = 0x09; 40 41 void printGUID(uint8_t *guid, off_t offset) 42 { 43 std::cout << "Read GUID from offset : " << offset << " :\n"; 44 for (int i = 0; i < GUID_SIZE; i++) 45 { 46 int data = guid[i]; 47 std::cout << std::hex << data << " "; 48 } 49 std::cout << std::endl; 50 } 51 52 int getGUID(off_t offset, uint8_t *guid) 53 { 54 int fd = -1; 55 ssize_t bytes_rd; 56 int ret = 0; 57 58 errno = 0; 59 60 // Check if file is present 61 if (access(FRU_EEPROM, F_OK) == -1) 62 { 63 std::cerr << "Unable to access: " << FRU_EEPROM << std::endl; 64 return errno; 65 } 66 67 // Open the file 68 fd = open(FRU_EEPROM, O_RDONLY); 69 if (fd == -1) 70 { 71 std::cerr << "Unable to open: " << FRU_EEPROM << std::endl; 72 return errno; 73 } 74 75 // seek to the offset 76 lseek(fd, offset, SEEK_SET); 77 78 // Read bytes from location 79 bytes_rd = read(fd, guid, GUID_SIZE); 80 if (bytes_rd != GUID_SIZE) 81 { 82 phosphor::logging::log<phosphor::logging::level::ERR>( 83 "GUID read data from EEPROM failed"); 84 ret = errno; 85 } 86 else 87 { 88 printGUID(guid, offset); 89 } 90 close(fd); 91 return ret; 92 } 93 94 int getSystemGUID(uint8_t *guid) 95 { 96 return getGUID(OFFSET_SYS_GUID, guid); 97 } 98 99 int getDeviceGUID(uint8_t *guid) 100 { 101 return getGUID(OFFSET_DEV_GUID, guid); 102 } 103 104 //---------------------------------------------------------------------- 105 // Get Device GUID (CMD_APP_GET_DEV_GUID) 106 //---------------------------------------------------------------------- 107 ipmi_ret_t ipmiAppGetDevGUID(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 108 ipmi_request_t request, ipmi_response_t response, 109 ipmi_data_len_t data_len, ipmi_context_t context) 110 { 111 uint8_t *res = reinterpret_cast<uint8_t *>(response); 112 113 if (getDeviceGUID(res)) 114 { 115 return IPMI_CC_UNSPECIFIED_ERROR; 116 } 117 *data_len = GUID_SIZE; 118 119 return IPMI_CC_OK; 120 } 121 122 //---------------------------------------------------------------------- 123 // Set Global Enables (CMD_APP_SET_GLOBAL_ENABLES) 124 //---------------------------------------------------------------------- 125 ipmi_ret_t ipmiAppSetGlobalEnables(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 126 ipmi_request_t request, 127 ipmi_response_t response, 128 ipmi_data_len_t data_len, 129 ipmi_context_t context) 130 { 131 uint8_t *req = reinterpret_cast<uint8_t *>(request); 132 133 globEna = *req; 134 *data_len = 0; 135 136 return IPMI_CC_OK; 137 } 138 139 //---------------------------------------------------------------------- 140 // Get Global Enables (CMD_APP_GET_GLOBAL_ENABLES) 141 //---------------------------------------------------------------------- 142 ipmi_ret_t ipmiAppGetGlobalEnables(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 143 ipmi_request_t request, 144 ipmi_response_t response, 145 ipmi_data_len_t data_len, 146 ipmi_context_t context) 147 { 148 uint8_t *res = reinterpret_cast<uint8_t *>(response); 149 150 *data_len = 1; 151 *res++ = globEna; 152 153 return IPMI_CC_OK; 154 } 155 156 //---------------------------------------------------------------------- 157 // Get System GUID (CMD_APP_GET_SYS_GUID) 158 //---------------------------------------------------------------------- 159 ipmi_ret_t ipmiAppGetSysGUID(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 160 ipmi_request_t request, ipmi_response_t response, 161 ipmi_data_len_t data_len, ipmi_context_t context) 162 { 163 uint8_t *res = reinterpret_cast<uint8_t *>(response); 164 if (getSystemGUID(res)) 165 { 166 return IPMI_CC_UNSPECIFIED_ERROR; 167 } 168 *data_len = GUID_SIZE; 169 return IPMI_CC_OK; 170 } 171 172 void registerAPPFunctions() 173 { 174 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_DEV_GUID, NULL, 175 ipmiAppGetDevGUID, 176 PRIVILEGE_USER); // Get Device GUID 177 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_SET_GLOBAL_ENABLES, NULL, 178 ipmiAppSetGlobalEnables, 179 PRIVILEGE_USER); // Get Global Enables 180 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_GLOBAL_ENABLES, NULL, 181 ipmiAppGetGlobalEnables, 182 PRIVILEGE_USER); // Get Global Enables 183 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_SYS_GUID, NULL, 184 ipmiAppGetSysGUID, 185 PRIVILEGE_USER); // Get System GUID 186 187 return; 188 } 189 190 } // namespace ipmi 191