123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640 |
- /*
- * Copyright (c) 2003 Kontron Canada, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind.
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
- * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
- * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
- * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
- * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
- * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
- * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
- * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
- * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- */
- #include <string.h>
- #include <math.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <time.h>
- #include <ipmitool/ipmi.h>
- #include <ipmitool/log.h>
- #include <ipmitool/ipmi_mc.h>
- #include <ipmitool/ipmi_sdr.h>
- #include <ipmitool/ipmi_gendev.h>
- #include <ipmitool/ipmi_intf.h>
- #include <ipmitool/ipmi_sel.h>
- #include <ipmitool/ipmi_entity.h>
- #include <ipmitool/ipmi_constants.h>
- #include <ipmitool/ipmi_strings.h>
- #include <ipmitool/ipmi_raw.h>
- #if HAVE_CONFIG_H
- # include <config.h>
- #endif
- extern int verbose;
- #define GENDEV_RETRY_COUNT 5
- #define GENDEV_MAX_SIZE 16
- typedef struct gendev_eeprom_info
- {
- uint32_t size;
- uint16_t page_size;
- uint8_t address_span;
- uint8_t address_length;
- }t_gendev_eeprom_info;
- static int
- ipmi_gendev_get_eeprom_size(
- struct ipmi_intf *intf,
- struct sdr_record_generic_locator *dev,
- t_gendev_eeprom_info *info
- )
- {
- int eeprom_size = 0;
- /*
- lprintf(LOG_ERR, "Gen Device : %s", dev->id_string);
- lprintf(LOG_ERR, "Access Addr: %x", dev->dev_access_addr);
- lprintf(LOG_ERR, "Slave Addr : %x", dev->dev_slave_addr);
- lprintf(LOG_ERR, "Channel Num: %x", dev->channel_num);
- lprintf(LOG_ERR, "Lun : %x", dev->lun);
- lprintf(LOG_ERR, "Bus : %x", dev->bus);
- lprintf(LOG_ERR, "Addr Span : %x", dev->addr_span);
- lprintf(LOG_ERR, "DevType : %x", dev->dev_type);
- lprintf(LOG_ERR, "DevType Mod: %x", dev->dev_type_modifier);
- */
- if( info != NULL)
- {
- switch(dev->dev_type)
- {
- case 0x08: // 24C01
- info->size = 128;
- info->page_size = 8;
- info->address_span = dev->addr_span;
- info->address_length = 1;
- break;
- case 0x09: // 24C02
- info->size = 256;
- info->page_size = 8;
- info->address_span = dev->addr_span;
- info->address_length = 1;
- break;
- case 0x0A: // 24C04
- info->size = 512;
- info->page_size = 8;
- info->address_span = dev->addr_span;
- info->address_length = 2;
- break;
- case 0x0B: // 24C08
- info->size = 1024;
- info->page_size = 8;
- info->address_span = dev->addr_span;
- info->address_length = 2;
- break;
- case 0x0C: // 24C16
- info->size = 2048;
- info->page_size = 256;
- info->address_span = dev->addr_span;
- info->address_length = 2;
- break;
- case 0x0D: // 24C17
- info->size = 2048;
- info->page_size = 256;
- info->address_span = dev->addr_span;
- info->address_length = 2;
- break;
- case 0x0E: // 24C32
- info->size = 4096;
- info->page_size = 8;
- info->address_span = dev->addr_span;
- info->address_length = 2;
- break;
- case 0x0F: // 24C64
- info->size = 8192;
- info->page_size = 32;
- info->address_span = dev->addr_span;
- info->address_length = 2;
- break;
- case 0xC0: // Proposed OEM Code for 24C128
- info->size = 16384;
- info->page_size = 64;
- info->address_span = dev->addr_span;
- info->address_length = 2;
- break;
- case 0xC1: // Proposed OEM Code for 24C256
- info->size = 32748;
- info->page_size = 64;
- info->address_span = dev->addr_span;
- info->address_length = 2;
- break;
- case 0xC2: // Proposed OEM Code for 24C512
- info->size = 65536;
- info->page_size = 128;
- info->address_span = dev->addr_span;
- info->address_length = 2;
- break;
- case 0xC3: // Proposed OEM Code for 24C1024
- info->size = 131072;
- info->page_size = 128;
- info->address_span = dev->addr_span;
- info->address_length = 2;
- break;
- /* Please reserved up to CFh for future update */
- default: // Not a eeprom, return size = 0;
- info->size = 0;
- info->page_size = 0;
- info->address_span = 0;
- info->address_length = 0;
- break;
- }
-
- eeprom_size = info->size;
- }
- return eeprom_size;
- }
- static int
- ipmi_gendev_read_file(
- struct ipmi_intf *intf,
- struct sdr_record_generic_locator *dev,
- const char *ofile
- )
- {
- int rc = 0;
- int eeprom_size;
- t_gendev_eeprom_info eeprom_info;
- eeprom_size = ipmi_gendev_get_eeprom_size(intf, dev, &eeprom_info);
- if(eeprom_size > 0)
- {
- FILE *fp;
-
- /* now write to file */
- fp = ipmi_open_file_write(ofile);
- if(fp)
- {
- struct ipmi_rs *rsp;
- int numWrite;
- uint32_t counter;
- uint8_t msize;
- uint8_t channel = dev->channel_num;
- uint8_t i2cbus = dev->bus;
- uint8_t i2caddr = dev->dev_slave_addr;
- uint8_t privatebus = 1;
- uint32_t address_span_size;
- uint8_t percentCompleted = 0;
- /* Handle Address Span */
- if( eeprom_info.address_span != 0)
- {
- address_span_size =
- (eeprom_info.size / (eeprom_info.address_span+1));
- }
- else
- {
- address_span_size = eeprom_info.size;
- }
- /* Setup read/write size */
- if( eeprom_info.page_size < GENDEV_MAX_SIZE)
- {
- msize = eeprom_info.page_size;
- }
- else
- {
- msize = GENDEV_MAX_SIZE;
- // All eeprom with page higher than 32 is on the
- // 16 bytes boundary
- }
- /* Setup i2c bus byte */
- i2cbus = ((channel & 0xF) << 4) | ((i2cbus & 7) << 1) | privatebus;
- /*
- lprintf(LOG_ERR, "Generic device: %s", dev->id_string);
- lprintf(LOG_ERR, "I2C Chnl: %x", channel);
- lprintf(LOG_ERR, "I2C Bus : %x", i2cbus);
- lprintf(LOG_ERR, "I2C Addr: %x", i2caddr); */
- for (
- counter = 0;
- (counter < (eeprom_info.size)) && (rc == 0);
- counter+= msize
- )
- {
- uint8_t retryCounter;
- for(
- retryCounter = 0;
- retryCounter<GENDEV_RETRY_COUNT;
- retryCounter ++
- )
- {
- uint8_t wrByte[GENDEV_MAX_SIZE+2];
- wrByte[0] = (uint8_t) (counter>>0);
- if(eeprom_info.address_length > 1)
- {
- wrByte[1] = (uint8_t) (counter>>8);
- }
-
- i2caddr+= (((eeprom_info.size) % address_span_size) * 2);
-
- rsp = ipmi_master_write_read(
- intf,
- i2cbus,
- i2caddr,
- (uint8_t *) wrByte,
- eeprom_info.address_length,
- msize
- );
- if (rsp != NULL)
- {
- retryCounter = GENDEV_RETRY_COUNT;
- rc = 0;
- }
- else if(retryCounter < GENDEV_RETRY_COUNT)
- {
- retryCounter ++;
- lprintf(LOG_ERR, "Retry");
- sleep(1);
- rc = -1;
- }
- else
- {
- lprintf(LOG_ERR, "Unable to perform I2C Master Write-Read");
- rc = -1;
- }
- }
- if( rc == 0 )
- {
- static uint8_t previousCompleted = 101;
- numWrite = fwrite(rsp->data, 1, msize, fp);
- if (numWrite != msize)
- {
- lprintf(LOG_ERR, "Error writing file %s", ofile);
- rc = -1;
- break;
- }
- percentCompleted = ((counter * 100) / eeprom_info.size );
-
- if(percentCompleted != previousCompleted)
- {
- printf("\r%i percent completed", percentCompleted);
- previousCompleted = percentCompleted;
- }
- }
- }
- if(counter == (eeprom_info.size))
- {
- printf("\r%%100 percent completed\n");
- }
- else
- {
- printf("\rError: %i percent completed, read not completed \n", percentCompleted);
- }
- fclose(fp);
- }
- }
- else
- {
- lprintf(LOG_ERR, "The selected generic device is not an eeprom");
- }
- return rc;
- }
- /* ipmi_gendev_write_file - Read raw SDR from binary file
- *
- * used for writing generic locator device Eeprom type
- *
- * @intf: ipmi interface
- * @dev: generic device to read
- * @ofile: output filename
- *
- * returns 0 on success
- * returns -1 on error
- */
- static int
- ipmi_gendev_write_file(
- struct ipmi_intf *intf,
- struct sdr_record_generic_locator *dev,
- const char *ofile
- )
- {
- int rc = 0;
- int eeprom_size;
- t_gendev_eeprom_info eeprom_info;
- eeprom_size = ipmi_gendev_get_eeprom_size(intf, dev, &eeprom_info);
- if(eeprom_size > 0)
- {
- FILE *fp;
- uint32_t fileLength = 0;
-
- /* now write to file */
- fp = ipmi_open_file_read(ofile);
-
- if(fp)
- {
- /* Retreive file length, check if it's fits the Eeprom Size */
- fseek(fp, 0 ,SEEK_END);
- fileLength = ftell(fp);
- lprintf(LOG_ERR, "File Size: %i", fileLength);
- lprintf(LOG_ERR, "Eeprom Size: %i", eeprom_size);
- if(fileLength != eeprom_size)
- {
- lprintf(LOG_ERR, "File size does not fit Eeprom Size");
- fclose(fp);
- fp = NULL;
- }
- else
- {
- fseek(fp, 0 ,SEEK_SET);
- }
- }
-
- if(fp)
- {
- struct ipmi_rs *rsp;
- int numRead;
- uint32_t counter;
- uint8_t msize;
- uint8_t channel = dev->channel_num;
- uint8_t i2cbus = dev->bus;
- uint8_t i2caddr = dev->dev_slave_addr;
- uint8_t privatebus = 1;
- uint32_t address_span_size;
- uint8_t percentCompleted = 0;
- /* Handle Address Span */
- if( eeprom_info.address_span != 0)
- {
- address_span_size =
- (eeprom_info.size / (eeprom_info.address_span+1));
- }
- else
- {
- address_span_size = eeprom_info.size;
- }
- /* Setup read/write size */
- if( eeprom_info.page_size < GENDEV_MAX_SIZE)
- {
- msize = eeprom_info.page_size;
- }
- else
- {
- msize = GENDEV_MAX_SIZE;
- // All eeprom with page higher than 32 is on the
- // 16 bytes boundary
- }
- /* Setup i2c bus byte */
- i2cbus = ((channel & 0xF) << 4) | ((i2cbus & 7) << 1) | privatebus;
- /*
- lprintf(LOG_ERR, "Generic device: %s", dev->id_string);
- lprintf(LOG_ERR, "I2C Chnl: %x", channel);
- lprintf(LOG_ERR, "I2C Bus : %x", i2cbus);
- lprintf(LOG_ERR, "I2C Addr: %x", i2caddr); */
- for (
- counter = 0;
- (counter < (eeprom_info.size)) && (rc == 0);
- counter+= msize
- )
- {
- uint8_t retryCounter;
- uint8_t readByte[GENDEV_MAX_SIZE];
- numRead = fread(readByte, 1, msize, fp);
- if (numRead != msize)
- {
- lprintf(LOG_ERR, "Error reading file %s", ofile);
- rc = -1;
- break;
- }
- for(
- retryCounter = 0;
- retryCounter<GENDEV_RETRY_COUNT;
- retryCounter ++
- )
- {
- uint8_t wrByte[GENDEV_MAX_SIZE+2];
- wrByte[0] = (uint8_t) (counter>>0);
- if(eeprom_info.address_length > 1)
- {
- wrByte[1] = (uint8_t) (counter>>8);
- }
- memcpy(&wrByte[eeprom_info.address_length], readByte, msize);
- i2caddr+= (((eeprom_info.size) % address_span_size) * 2);
- rsp = ipmi_master_write_read(intf, i2cbus, i2caddr, (uint8_t *) wrByte, eeprom_info.address_length+msize, 0);
- if (rsp != NULL)
- {
- retryCounter = GENDEV_RETRY_COUNT;
- rc = 0;
- }
- else if(retryCounter < GENDEV_RETRY_COUNT)
- {
- retryCounter ++;
- lprintf(LOG_ERR, "Retry");
- sleep(1);
- rc = -1;
- }
- else
- {
- lprintf(LOG_ERR, "Unable to perform I2C Master Write-Read");
- rc = -1;
- }
- }
- if( rc == 0 )
- {
- static uint8_t previousCompleted = 101;
- percentCompleted = ((counter * 100) / eeprom_info.size );
- if(percentCompleted != previousCompleted)
- {
- printf("\r%i percent completed", percentCompleted);
- previousCompleted = percentCompleted;
- }
- }
- }
- if(counter == (eeprom_info.size))
- {
- printf("\r%%100 percent completed\n");
- }
- else
- {
- printf("\rError: %i percent completed, read not completed \n", percentCompleted);
- }
- fclose(fp);
- }
- }
- else
- {
- lprintf(LOG_ERR, "The selected generic device is not an eeprom");
- }
- return rc;
- }
- /* ipmi_gendev_main - top-level handler for generic device
- *
- * @intf: ipmi interface
- * @argc: number of arguments
- * @argv: argument list
- *
- * returns 0 on success
- * returns -1 on error
- */
- int
- ipmi_gendev_main(struct ipmi_intf *intf, int argc, char **argv)
- {
- int rc = 0;
- /* initialize random numbers used later */
- srand(time(NULL));
- lprintf(LOG_ERR, "Rx gendev command: %s", argv[0]);
- if (
- (argc == 0)
- ||
- (strncmp(argv[0], "help", 4) == 0)
- )
- {
- lprintf(LOG_ERR,
- "SDR Commands: list read write");
- lprintf(LOG_ERR,
- " list List All Generic Device Locators");
- lprintf(LOG_ERR,
- " read <sdr name> <file> Read to file eeprom specify by Generic Device Locators");
- lprintf(LOG_ERR,
- " write <sdr name> <file> Write from file eeprom specify by Generic Device Locators");
- }
- else if ( strncmp(argv[0], "list", 4) == 0)
- {
- rc = ipmi_sdr_print_sdr(intf,
- SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
- }
- else if (strncmp(argv[0], "read", 4) == 0)
- {
- if (argc < 3)
- lprintf(LOG_ERR, "usage: gendev read <gendev> <filename>");
- else
- {
- struct sdr_record_list *sdr;
- lprintf(LOG_ERR, "Gendev read sdr name : %s", argv[1]);
- printf("Locating sensor record '%s'...\n", argv[1]);
- /* lookup by sensor name */
- sdr = ipmi_sdr_find_sdr_byid(intf, argv[1]);
- if (sdr == NULL)
- {
- lprintf(LOG_ERR, "Sensor data record not found!");
- return -1;
- }
- if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
- {
- lprintf(LOG_ERR, "Target SDR is not a generic device locator");
- return -1;
- }
- lprintf(LOG_ERR, "Gendev read file name: %s", argv[2]);
- ipmi_gendev_read_file(intf, sdr->record.genloc, argv[2]);
- }
- }
- else if (strncmp(argv[0], "write", 5) == 0)
- {
- if (argc < 3)
- lprintf(LOG_ERR, "usage: gendev write <gendev> <filename>");
- else
- {
- struct sdr_record_list *sdr;
- lprintf(LOG_ERR, "Gendev write sdr name : %s", argv[1]);
- printf("Locating sensor record '%s'...\n", argv[1]);
- /* lookup by sensor name */
- sdr = ipmi_sdr_find_sdr_byid(intf, argv[1]);
- if (sdr == NULL)
- {
- lprintf(LOG_ERR, "Sensor data record not found!");
- return -1;
- }
- if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
- {
- lprintf(LOG_ERR, "Target SDR is not a generic device locator");
- return -1;
- }
- lprintf(LOG_ERR, "Gendev write file name: %s", argv[2]);
- ipmi_gendev_write_file(intf, sdr->record.genloc, argv[2]);
- }
- }
- else
- {
- lprintf(LOG_ERR, "Invalid gendev command: %s", argv[0]);
- rc = -1;
- }
- return rc;
- }
|