1/* 2 * Copyright (C) 2012 CERN (www.cern.ch) 3 * Author: Alessandro Rubini <rubini@gnudd.com> 4 * 5 * Released according to the GNU GPL, version 2 or any later version. 6 * 7 * This work is part of the White Rabbit project, a research effort led 8 * by CERN, the European Institute for Nuclear Research. 9 */ 10#ifndef __LINUX_IPMI_FRU_H__ 11#define __LINUX_IPMI_FRU_H__ 12#ifdef __KERNEL__ 13# include <linux/types.h> 14# include <linux/string.h> 15#else 16# include <stdint.h> 17# include <string.h> 18#endif 19 20/* 21 * These structures match the unaligned crap we have in FRU1011.pdf 22 * (http://download.intel.com/design/servers/ipmi/FRU1011.pdf) 23 */ 24 25/* chapter 8, page 5 */ 26struct fru_common_header { 27 uint8_t format; /* 0x01 */ 28 uint8_t internal_use_off; /* multiple of 8 bytes */ 29 uint8_t chassis_info_off; /* multiple of 8 bytes */ 30 uint8_t board_area_off; /* multiple of 8 bytes */ 31 uint8_t product_area_off; /* multiple of 8 bytes */ 32 uint8_t multirecord_off; /* multiple of 8 bytes */ 33 uint8_t pad; /* must be 0 */ 34 uint8_t checksum; /* sum modulo 256 must be 0 */ 35}; 36 37/* chapter 9, page 5 -- internal_use: not used by us */ 38 39/* chapter 10, page 6 -- chassis info: not used by us */ 40 41/* chapter 13, page 9 -- used by board_info_area below */ 42struct fru_type_length { 43 uint8_t type_length; 44 uint8_t data[0]; 45}; 46 47/* chapter 11, page 7 */ 48struct fru_board_info_area { 49 uint8_t format; /* 0x01 */ 50 uint8_t area_len; /* multiple of 8 bytes */ 51 uint8_t language; /* I hope it's 0 */ 52 uint8_t mfg_date[3]; /* LSB, minutes since 1996-01-01 */ 53 struct fru_type_length tl[0]; /* type-length stuff follows */ 54 55 /* 56 * the TL there are in order: 57 * Board Manufacturer 58 * Board Product Name 59 * Board Serial Number 60 * Board Part Number 61 * FRU File ID (may be null) 62 * more manufacturer-specific stuff 63 * 0xc1 as a terminator 64 * 0x00 pad to a multiple of 8 bytes - 1 65 * checksum (sum of all stuff module 256 must be zero) 66 */ 67}; 68 69enum fru_type { 70 FRU_TYPE_BINARY = 0x00, 71 FRU_TYPE_BCDPLUS = 0x40, 72 FRU_TYPE_ASCII6 = 0x80, 73 FRU_TYPE_ASCII = 0xc0, /* not ascii: depends on language */ 74}; 75 76/* 77 * some helpers 78 */ 79static inline struct fru_board_info_area *fru_get_board_area( 80 const struct fru_common_header *header) 81{ 82 /* we know for sure that the header is 8 bytes in size */ 83 return (struct fru_board_info_area *)(header + header->board_area_off); 84} 85 86static inline int fru_type(struct fru_type_length *tl) 87{ 88 return tl->type_length & 0xc0; 89} 90 91static inline int fru_length(struct fru_type_length *tl) 92{ 93 return (tl->type_length & 0x3f) + 1; /* len of whole record */ 94} 95 96/* assume ascii-latin1 encoding */ 97static inline int fru_strlen(struct fru_type_length *tl) 98{ 99 return fru_length(tl) - 1; 100} 101 102static inline char *fru_strcpy(char *dest, struct fru_type_length *tl) 103{ 104 int len = fru_strlen(tl); 105 memcpy(dest, tl->data, len); 106 dest[len] = '\0'; 107 return dest; 108} 109 110static inline struct fru_type_length *fru_next_tl(struct fru_type_length *tl) 111{ 112 return tl + fru_length(tl); 113} 114 115static inline int fru_is_eof(struct fru_type_length *tl) 116{ 117 return tl->type_length == 0xc1; 118} 119 120/* 121 * External functions defined in fru-parse.c. 122 */ 123extern int fru_header_cksum_ok(struct fru_common_header *header); 124extern int fru_bia_cksum_ok(struct fru_board_info_area *bia); 125 126/* All these 4 return allocated strings by calling fru_alloc() */ 127extern char *fru_get_board_manufacturer(struct fru_common_header *header); 128extern char *fru_get_product_name(struct fru_common_header *header); 129extern char *fru_get_serial_number(struct fru_common_header *header); 130extern char *fru_get_part_number(struct fru_common_header *header); 131 132/* This must be defined by the caller of the above functions */ 133extern void *fru_alloc(size_t size); 134 135#endif /* __LINUX_IMPI_FRU_H__ */ 136