xref: /openbmc/ipmitool/lib/dimm_spd.c (revision 531569ec)
1 /*
2  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * Redistribution of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * Redistribution in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * Neither the name of Sun Microsystems, Inc. or the names of
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * This software is provided "AS IS," without a warranty of any kind.
20  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
26  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  */
32 
33 #include <ipmitool/ipmi.h>
34 #include <ipmitool/log.h>
35 #include <ipmitool/helper.h>
36 #include <ipmitool/ipmi_intf.h>
37 #include <ipmitool/ipmi_fru.h>
38 
39 #include <stdlib.h>
40 #include <string.h>
41 
42 extern int verbose;
43 
44 /*
45  * Also, see ipmi_fru.c.
46  *
47  * Apparently some systems have problems with FRU access greater than 16 bytes
48  * at a time, even when using byte (not word) access.	 In order to ensure we
49  * work with the widest variety of hardware request size is capped at 16 bytes.
50  * Since this may result in slowdowns on some systems with lots of FRU data you
51  * can change this define to enable larger (up to 32 bytes at a time) access.
52  */
53 #define FRU_DATA_RQST_SIZE 16;
54 
55 const struct valstr spd_memtype_vals[] = {
56 	{ 0x01, "STD FPM DRAM" },
57 	{ 0x02, "EDO" },
58 	{ 0x04, "SDRAM" },
59 	{ 0x05, "ROM" },
60 	{ 0x06, "DDR SGRAM" },
61 	{ 0x07, "DDR SDRAM" },
62 	{ 0x08, "DDR2 SDRAM" },
63 	{ 0x09, "DDR2 SDRAM FB-DIMM" },
64 	{ 0x0A, "DDR2 SDRAM FB-DIMM Probe" },
65 	{ 0x0B, "DDR3 SDRAM" },
66 	{ 0x0C, "DDR4 SDRAM" },
67 	{ 0x00, NULL },
68 };
69 
70 const struct valstr ddr3_density_vals[] =
71 {
72 	{ 0, "256 Mb" },
73 	{ 1, "512 Mb" },
74 	{ 2, "1 Gb" },
75 	{ 3, "2 Gb" },
76 	{ 4, "4 Gb" },
77 	{ 5, "8 Gb" },
78 	{ 6, "16 Gb" },
79 	{ 0x00, NULL },
80 };
81 
82 const struct valstr ddr3_banks_vals[] =
83 {
84 	{ 0, "3 (8 Banks)" },
85 	{ 1, "4 (16 Banks)" },
86 	{ 2, "5 (32 Banks)" },
87 	{ 3, "6 (64 Banks)" },
88 	{ 0x00, NULL },
89 };
90 
91 
92 #define ddr4_ecc_vals ddr3_ecc_vals
93 const struct valstr ddr3_ecc_vals[] =
94 {
95 	{ 0, "0 bits" },
96 	{ 1, "8 bits" },
97 	{ 0x00, NULL },
98 };
99 
100 const struct valstr ddr4_density_vals[] =
101 {
102 	{ 0, "256 Mb" },
103 	{ 1, "512 Mb" },
104 	{ 2, "1 Gb" },
105 	{ 3, "2 Gb" },
106 	{ 4, "4 Gb" },
107 	{ 5, "8 Gb" },
108 	{ 6, "16 Gb" },
109 	{ 7, "32 Gb" },
110 	{ 0x00, NULL },
111 };
112 
113 const struct valstr ddr4_banks_vals[] =
114 {
115 	{ 0, "2 (4 Banks)" },
116 	{ 1, "3 (8 Banks)" },
117 	{ 0x00, NULL },
118 };
119 
120 const struct valstr ddr4_bank_groups[] =
121 {
122 	{ 0, "0 (no Bank Groups)" },
123 	{ 1, "1 (2 Bank Groups)" },
124 	{ 2, "2 (4 Bank Groups)" },
125 	{ 0x00, NULL },
126 };
127 
128 const struct valstr ddr4_package_type[] =
129 {
130 	{ 0, "Monolithic DRAM Device" },
131 	{ 1, "Non-Monolithic Device" },
132 	{ 0x00, NULL },
133 };
134 
135 const struct valstr ddr4_technology_type[] =
136 {
137 	{ 0, "Extended module type, see byte 15" },
138 	{ 1, "RDIMM" },
139 	{ 2, "UDIMM" },
140 	{ 3, "SO-DIMM" },
141 	{ 4, "LRDIMM" },
142 	{ 5, "Mini-RDIMM" },
143 	{ 6, "Mini-UDIMM" },
144 	{ 7, "7 - Reserved" },
145 	{ 8, "72b-SO-RDIMM" },
146 	{ 9, "72b-SO-UDIMM" },
147 	{ 10, "10 - Reserved" },
148 	{ 11, "11 - Reserved" },
149 	{ 12, "16b-SO-DIMM" },
150 	{ 13, "32b-SO-DIMM" },
151 	{ 14, "14 - Reserved" },
152 	{ 15, "No base memory present" },
153 	{ 0x00, NULL },
154 };
155 
156 const struct valstr spd_config_vals[] = {
157 	{ 0x00, "None" },
158 	{ 0x01, "Parity" },
159 	{ 0x02, "ECC" },
160 	{ 0x04, "Addr Cmd Parity" },
161 	{ 0x00, NULL },
162 };
163 
164 const struct valstr spd_voltage_vals[] = {
165 	{ 0x00, "5.0V TTL" },
166 	{ 0x01, "LVTTL" },
167 	{ 0x02, "HSTL 1.5V" },
168 	{ 0x03, "SSTL 3.3V" },
169 	{ 0x04, "SSTL 2.5V" },
170 	{ 0x05, "SSTL 1.8V" },
171 	{ 0x00, NULL },
172 };
173 
174 /*
175  * JEDEC Standard Manufacturers Identification Code
176  * publication JEP106N, December 2003
177  */
178 
179 const struct valstr jedec_id1_vals[] = {
180 	{ 0x01, "AMD" },
181 	{ 0x02, "AMI" },
182 	{ 0x83, "Fairchild" },
183 	{ 0x04, "Fujitsu" },
184 	{ 0x85, "GTE" },
185 	{ 0x86, "Harris" },
186 	{ 0x07, "Hitachi" },
187 	{ 0x08, "Inmos" },
188 	{ 0x89, "Intel" },
189 	{ 0x8a, "I.T.T." },
190 	{ 0x0b, "Intersil" },
191 	{ 0x8c, "Monolithic Memories" },
192 	{ 0x0d, "Mostek" },
193 	{ 0x0e, "Motorola" },
194 	{ 0x8f, "National" },
195 	{ 0x10, "NEC" },
196 	{ 0x91, "RCA" },
197 	{ 0x92, "Raytheon" },
198 	{ 0x13, "Conexant (Rockwell)" },
199 	{ 0x94, "Seeq" },
200 	{ 0x15, "Philips Semi. (Signetics)" },
201 	{ 0x16, "Synertek" },
202 	{ 0x97, "Texas Instruments" },
203 	{ 0x98, "Toshiba" },
204 	{ 0x19, "Xicor" },
205 	{ 0x1a, "Zilog" },
206 	{ 0x9b, "Eurotechnique" },
207 	{ 0x1c, "Mitsubishi" },
208 	{ 0x9d, "Lucent (AT&T)" },
209 	{ 0x9e, "Exel" },
210 	{ 0x1f, "Atmel" },
211 	{ 0x20, "SGS/Thomson" },
212 	{ 0xa1, "Lattice Semi." },
213 	{ 0xa2, "NCR" },
214 	{ 0x23, "Wafer Scale Integration" },
215 	{ 0xa4, "IBM" },
216 	{ 0x25, "Tristar" },
217 	{ 0x26, "Visic" },
218 	{ 0xa7, "Intl. CMOS Technology" },
219 	{ 0xa8, "SSSI" },
220 	{ 0x29, "Microchip Technology" },
221 	{ 0x2a, "Ricoh Ltd." },
222 	{ 0xab, "VLSI" },
223 	{ 0x2c, "Micron Technology" },
224 	{ 0xad, "Hyundai Electronics" },
225 	{ 0xae, "OKI Semiconductor" },
226 	{ 0x2f, "ACTEL" },
227 	{ 0xb0, "Sharp" },
228 	{ 0x31, "Catalyst" },
229 	{ 0x32, "Panasonic" },
230 	{ 0xb3, "IDT" },
231 	{ 0x34, "Cypress" },
232 	{ 0xb5, "DEC" },
233 	{ 0xb6, "LSI Logic" },
234 	{ 0x37, "Zarlink" },
235 	{ 0x38, "UTMC" },
236 	{ 0xb9, "Thinking Machine" },
237 	{ 0xba, "Thomson CSF" },
238 	{ 0x3b, "Integrated CMOS(Vertex)" },
239 	{ 0xbc, "Honeywell" },
240 	{ 0x3d, "Tektronix" },
241 	{ 0x3e, "Sun Microsystems" },
242 	{ 0xbf, "SST" },
243 	{ 0x40, "MOSEL" },
244 	{ 0xc1, "Infineon" },
245 	{ 0xc2, "Macronix" },
246 	{ 0x43, "Xerox" },
247 	{ 0xc4, "Plus Logic" },
248 	{ 0x45, "SunDisk" },
249 	{ 0x46, "Elan Circuit Tech." },
250 	{ 0xc7, "European Silicon Str." },
251 	{ 0xc8, "Apple Computer" },
252 	{ 0xc9, "Xilinx" },
253 	{ 0x4a, "Compaq" },
254 	{ 0xcb, "Protocol Engines" },
255 	{ 0x4c, "SCI" },
256 	{ 0xcd, "Seiko Instruments" },
257 	{ 0xce, "Samsung" },
258 	{ 0x4f, "I3 Design System" },
259 	{ 0xd0, "Klic" },
260 	{ 0x51, "Crosspoint Solutions" },
261 	{ 0x52, "Alliance Semiconductor" },
262 	{ 0xd3, "Tandem" },
263 	{ 0x54, "Hewlett-Packard" },
264 	{ 0xd5, "Intg. Silicon Solutions" },
265 	{ 0xd6, "Brooktree" },
266 	{ 0x57, "New Media" },
267 	{ 0x58, "MHS Electronic" },
268 	{ 0xd9, "Performance Semi." },
269 	{ 0xda, "Winbond Electronic" },
270 	{ 0x5b, "Kawasaki Steel" },
271 	{ 0xdc, "Bright Micro" },
272 	{ 0x5d, "TECMAR" },
273 	{ 0x5e, "Exar" },
274 	{ 0xdf, "PCMCIA" },
275 	{ 0xe0, "LG Semiconductor" },
276 	{ 0x61, "Northern Telecom" },
277 	{ 0x62, "Sanyo" },
278 	{ 0xe3, "Array Microsystems" },
279 	{ 0x64, "Crystal Semiconductor" },
280 	{ 0xe5, "Analog Devices" },
281 	{ 0xe6, "PMC-Sierra" },
282 	{ 0x67, "Asparix" },
283 	{ 0x68, "Convex Computer" },
284 	{ 0xe9, "Quality Semiconductor" },
285 	{ 0xea, "Nimbus Technology" },
286 	{ 0x6b, "Transwitch" },
287 	{ 0xec, "Micronas (ITT Intermetall)" },
288 	{ 0x6d, "Cannon" },
289 	{ 0x6e, "Altera" },
290 	{ 0xef, "NEXCOM" },
291 	{ 0x70, "QUALCOMM" },
292 	{ 0xf1, "Sony" },
293 	{ 0xf2, "Cray Research" },
294 	{ 0x73, "AMS (Austria Micro)" },
295 	{ 0xf4, "Vitesse" },
296 	{ 0x75, "Aster Electronics" },
297 	{ 0x76, "Bay Networks (Synoptic)" },
298 	{ 0xf7, "Zentrum" },
299 	{ 0xf8, "TRW" },
300 	{ 0x79, "Thesys" },
301 	{ 0x7a, "Solbourne Computer" },
302 	{ 0xfb, "Allied-Signal" },
303 	{ 0x7c, "Dialog" },
304 	{ 0xfd, "Media Vision" },
305 	{ 0xfe, "Level One Communication" },
306 	{ 0x00, NULL },
307 };
308 
309 const struct valstr jedec_id2_vals[] = {
310 	{ 0x01, "Cirrus Logic" },
311 	{ 0x02, "National Instruments" },
312 	{ 0x83, "ILC Data Device" },
313 	{ 0x04, "Alcatel Mietec" },
314 	{ 0x85, "Micro Linear" },
315 	{ 0x86, "Univ. of NC" },
316 	{ 0x07, "JTAG Technologies" },
317 	{ 0x08, "Loral" },
318 	{ 0x89, "Nchip" },
319 	{ 0x8A, "Galileo Tech" },
320 	{ 0x0B, "Bestlink Systems" },
321 	{ 0x8C, "Graychip" },
322 	{ 0x0D, "GENNUM" },
323 	{ 0x0E, "VideoLogic" },
324 	{ 0x8F, "Robert Bosch" },
325 	{ 0x10, "Chip Express" },
326 	{ 0x91, "DATARAM" },
327 	{ 0x92, "United Microelec Corp." },
328 	{ 0x13, "TCSI" },
329 	{ 0x94, "Smart Modular" },
330 	{ 0x15, "Hughes Aircraft" },
331 	{ 0x16, "Lanstar Semiconductor" },
332 	{ 0x97, "Qlogic" },
333 	{ 0x98, "Kingston" },
334 	{ 0x19, "Music Semi" },
335 	{ 0x1A, "Ericsson Components" },
336 	{ 0x9B, "SpaSE" },
337 	{ 0x1C, "Eon Silicon Devices" },
338 	{ 0x9D, "Programmable Micro Corp" },
339 	{ 0x9E, "DoD" },
340 	{ 0x1F, "Integ. Memories Tech." },
341 	{ 0x20, "Corollary Inc." },
342 	{ 0xA1, "Dallas Semiconductor" },
343 	{ 0xA2, "Omnivision" },
344 	{ 0x23, "EIV(Switzerland)" },
345 	{ 0xA4, "Novatel Wireless" },
346 	{ 0x25, "Zarlink (formerly Mitel)" },
347 	{ 0x26, "Clearpoint" },
348 	{ 0xA7, "Cabletron" },
349 	{ 0xA8, "Silicon Technology" },
350 	{ 0x29, "Vanguard" },
351 	{ 0x2A, "Hagiwara Sys-Com" },
352 	{ 0xAB, "Vantis" },
353 	{ 0x2C, "Celestica" },
354 	{ 0xAD, "Century" },
355 	{ 0xAE, "Hal Computers" },
356 	{ 0x2F, "Rohm Company Ltd." },
357 	{ 0xB0, "Juniper Networks" },
358 	{ 0x31, "Libit Signal Processing" },
359 	{ 0x32, "Enhanced Memories Inc." },
360 	{ 0xB3, "Tundra Semiconductor" },
361 	{ 0x34, "Adaptec Inc." },
362 	{ 0xB5, "LightSpeed Semi." },
363 	{ 0xB6, "ZSP Corp." },
364 	{ 0x37, "AMIC Technology" },
365 	{ 0x38, "Adobe Systems" },
366 	{ 0xB9, "Dynachip" },
367 	{ 0xBA, "PNY Electronics" },
368 	{ 0x3B, "Newport Digital" },
369 	{ 0xBC, "MMC Networks" },
370 	{ 0x3D, "T Square" },
371 	{ 0x3E, "Seiko Epson" },
372 	{ 0xBF, "Broadcom" },
373 	{ 0x40, "Viking Components" },
374 	{ 0xC1, "V3 Semiconductor" },
375 	{ 0xC2, "Flextronics (formerly Orbit)" },
376 	{ 0x43, "Suwa Electronics" },
377 	{ 0xC4, "Transmeta" },
378 	{ 0x45, "Micron CMS" },
379 	{ 0x46, "American Computer & Digital Components Inc" },
380 	{ 0xC7, "Enhance 3000 Inc" },
381 	{ 0xC8, "Tower Semiconductor" },
382 	{ 0x49, "CPU Design" },
383 	{ 0x4A, "Price Point" },
384 	{ 0xCB, "Maxim Integrated Product" },
385 	{ 0x4C, "Tellabs" },
386 	{ 0xCD, "Centaur Technology" },
387 	{ 0xCE, "Unigen Corporation" },
388 	{ 0x4F, "Transcend Information" },
389 	{ 0xD0, "Memory Card Technology" },
390 	{ 0x51, "CKD Corporation Ltd." },
391 	{ 0x52, "Capital Instruments, Inc." },
392 	{ 0xD3, "Aica Kogyo, Ltd." },
393 	{ 0x54, "Linvex Technology" },
394 	{ 0xD5, "MSC Vertriebs GmbH" },
395 	{ 0xD6, "AKM Company, Ltd." },
396 	{ 0x57, "Dynamem, Inc." },
397 	{ 0x58, "NERA ASA" },
398 	{ 0xD9, "GSI Technology" },
399 	{ 0xDA, "Dane-Elec (C Memory)" },
400 	{ 0x5B, "Acorn Computers" },
401 	{ 0xDC, "Lara Technology" },
402 	{ 0x5D, "Oak Technology, Inc." },
403 	{ 0x5E, "Itec Memory" },
404 	{ 0xDF, "Tanisys Technology" },
405 	{ 0xE0, "Truevision" },
406 	{ 0x61, "Wintec Industries" },
407 	{ 0x62, "Super PC Memory" },
408 	{ 0xE3, "MGV Memory" },
409 	{ 0x64, "Galvantech" },
410 	{ 0xE5, "Gadzoox Nteworks" },
411 	{ 0xE6, "Multi Dimensional Cons." },
412 	{ 0x67, "GateField" },
413 	{ 0x68, "Integrated Memory System" },
414 	{ 0xE9, "Triscend" },
415 	{ 0xEA, "XaQti" },
416 	{ 0x6B, "Goldenram" },
417 	{ 0xEC, "Clear Logic" },
418 	{ 0x6D, "Cimaron Communications" },
419 	{ 0x6E, "Nippon Steel Semi. Corp." },
420 	{ 0xEF, "Advantage Memory" },
421 	{ 0x70, "AMCC" },
422 	{ 0xF1, "LeCroy" },
423 	{ 0xF2, "Yamaha Corporation" },
424 	{ 0x73, "Digital Microwave" },
425 	{ 0xF4, "NetLogic Microsystems" },
426 	{ 0x75, "MIMOS Semiconductor" },
427 	{ 0x76, "Advanced Fibre" },
428 	{ 0xF7, "BF Goodrich Data." },
429 	{ 0xF8, "Epigram" },
430 	{ 0x79, "Acbel Polytech Inc." },
431 	{ 0x7A, "Apacer Technology" },
432 	{ 0xFB, "Admor Memory" },
433 	{ 0x7C, "FOXCONN" },
434 	{ 0xFD, "Quadratics Superconductor" },
435 	{ 0xFE, "3COM" },
436 	{ 0x00, NULL },
437 };
438 
439 const struct valstr jedec_id3_vals[] = {
440 	{ 0x01, "Camintonn Corporation" },
441 	{ 0x02, "ISOA Incorporated" },
442 	{ 0x83, "Agate Semiconductor" },
443 	{ 0x04, "ADMtek Incorporated" },
444 	{ 0x85, "HYPERTEC" },
445 	{ 0x86, "Adhoc Technologies" },
446 	{ 0x07, "MOSAID Technologies" },
447 	{ 0x08, "Ardent Technologies" },
448 	{ 0x89, "Switchcore" },
449 	{ 0x8A, "Cisco Systems, Inc." },
450 	{ 0x0B, "Allayer Technologies" },
451 	{ 0x8C, "WorkX AG" },
452 	{ 0x0D, "Oasis Semiconductor" },
453 	{ 0x0E, "Novanet Semiconductor" },
454 	{ 0x8F, "E-M Solutions" },
455 	{ 0x10, "Power General" },
456 	{ 0x91, "Advanced Hardware Arch." },
457 	{ 0x92, "Inova Semiconductors GmbH" },
458 	{ 0x13, "Telocity" },
459 	{ 0x94, "Delkin Devices" },
460 	{ 0x15, "Symagery Microsystems" },
461 	{ 0x16, "C-Port Corporation" },
462 	{ 0x97, "SiberCore Technologies" },
463 	{ 0x98, "Southland Microsystems" },
464 	{ 0x19, "Malleable Technologies" },
465 	{ 0x1A, "Kendin Communications" },
466 	{ 0x9B, "Great Technology Microcomputer" },
467 	{ 0x1C, "Sanmina Corporation" },
468 	{ 0x9D, "HADCO Corporation" },
469 	{ 0x9E, "Corsair" },
470 	{ 0x1F, "Actrans System Inc." },
471 	{ 0x20, "ALPHA Technologies" },
472 	{ 0xA1, "Cygnal Integrated Products Incorporated" },
473 	{ 0xA2, "Artesyn Technologies" },
474 	{ 0x23, "Align Manufacturing" },
475 	{ 0xA4, "Peregrine Semiconductor" },
476 	{ 0x25, "Chameleon Systems" },
477 	{ 0x26, "Aplus Flash Technology" },
478 	{ 0xA7, "MIPS Technologies" },
479 	{ 0xA8, "Chrysalis ITS" },
480 	{ 0x29, "ADTEC Corporation" },
481 	{ 0x2A, "Kentron Technologies" },
482 	{ 0xAB, "Win Technologies" },
483 	{ 0x2C, "ASIC Designs Inc" },
484 	{ 0xAD, "Extreme Packet Devices" },
485 	{ 0xAE, "RF Micro Devices" },
486 	{ 0x2F, "Siemens AG" },
487 	{ 0xB0, "Sarnoff Corporation" },
488 	{ 0x31, "Itautec Philco SA" },
489 	{ 0x32, "Radiata Inc." },
490 	{ 0xB3, "Benchmark Elect. (AVEX)" },
491 	{ 0x34, "Legend" },
492 	{ 0xB5, "SpecTek Incorporated" },
493 	{ 0xB6, "Hi/fn" },
494 	{ 0x37, "Enikia Incorporated" },
495 	{ 0x38, "SwitchOn Networks" },
496 	{ 0xB9, "AANetcom Incorporated" },
497 	{ 0xBA, "Micro Memory Bank" },
498 	{ 0x3B, "ESS Technology" },
499 	{ 0xBC, "Virata Corporation" },
500 	{ 0x3D, "Excess Bandwidth" },
501 	{ 0x3E, "West Bay Semiconductor" },
502 	{ 0xBF, "DSP Group" },
503 	{ 0x40, "Newport Communications" },
504 	{ 0xC1, "Chip2Chip Incorporated" },
505 	{ 0xC2, "Phobos Corporation" },
506 	{ 0x43, "Intellitech Corporation" },
507 	{ 0xC4, "Nordic VLSI ASA" },
508 	{ 0x45, "Ishoni Networks" },
509 	{ 0x46, "Silicon Spice" },
510 	{ 0xC7, "Alchemy Semiconductor" },
511 	{ 0xC8, "Agilent Technologies" },
512 	{ 0x49, "Centillium Communications" },
513 	{ 0x4A, "W.L. Gore" },
514 	{ 0xCB, "HanBit Electronics" },
515 	{ 0x4C, "GlobeSpan" },
516         { 0xCD, "Element 14" },
517 	{ 0xCE, "Pycon" },
518 	{ 0x4F, "Saifun Semiconductors" },
519 	{ 0xD0, "Sibyte, Incorporated" },
520 	{ 0x51, "MetaLink Technologies" },
521 	{ 0x52, "Feiya Technology" },
522 	{ 0xD3, "I & C Technology" },
523 	{ 0x54, "Shikatronics" },
524 	{ 0xD5, "Elektrobit" },
525 	{ 0xD6, "Megic" },
526 	{ 0x57, "Com-Tier" },
527 	{ 0x58, "Malaysia Micro Solutions" },
528 	{ 0xD9, "Hyperchip" },
529 	{ 0xDA, "Gemstone Communications" },
530 	{ 0x5B, "Anadyne Microelectronics" },
531 	{ 0xDC, "3ParData" },
532 	{ 0x5D, "Mellanox Technologies" },
533 	{ 0x5E, "Tenx Technologies" },
534 	{ 0xDF, "Helix AG" },
535 	{ 0xE0, "Domosys" },
536 	{ 0x61, "Skyup Technology" },
537 	{ 0x62, "HiNT Corporation" },
538 	{ 0xE3, "Chiaro" },
539 	{ 0x64, "MCI Computer GMBH" },
540 	{ 0xE5, "Exbit Technology A/S" },
541 	{ 0xE6, "Integrated Technology Express" },
542 	{ 0x67, "AVED Memory" },
543 	{ 0x68, "Legerity" },
544 	{ 0xE9, "Jasmine Networks" },
545 	{ 0xEA, "Caspian Networks" },
546 	{ 0x6B, "nCUBE" },
547 	{ 0xEC, "Silicon Access Networks" },
548 	{ 0x6D, "FDK Corporation" },
549 	{ 0x6E, "High Bandwidth Access" },
550 	{ 0xEF, "MultiLink Technology" },
551 	{ 0x70, "BRECIS" },
552 	{ 0xF1, "World Wide Packets" },
553 	{ 0xF2, "APW" },
554 	{ 0x73, "Chicory Systems" },
555 	{ 0xF4, "Xstream Logic" },
556 	{ 0x75, "Fast-Chip" },
557 	{ 0x76, "Zucotto Wireless" },
558 	{ 0xF7, "Realchip" },
559 	{ 0xF8, "Galaxy Power" },
560 	{ 0x79, "eSilicon" },
561 	{ 0x7A, "Morphics Technology" },
562 	{ 0xFB, "Accelerant Networks" },
563 	{ 0x7C, "Silicon Wave" },
564 	{ 0xFD, "SandCraft" },
565 	{ 0xFE, "Elpida" },
566 	{ 0x00, NULL },
567 };
568 
569 const struct valstr jedec_id4_vals[] = {
570 	{ 0x01, "Solectron" },
571 	{ 0x02, "Optosys Technologies" },
572 	{ 0x83, "Buffalo (Formerly Melco)" },
573 	{ 0x04, "TriMedia Technologies" },
574 	{ 0x85, "Cyan Technologies" },
575 	{ 0x86, "Global Locate" },
576 	{ 0x07, "Optillion" },
577 	{ 0x08, "Terago Communications" },
578 	{ 0x89, "Ikanos Communications" },
579 	{ 0x8A, "Princeton Technology" },
580 	{ 0x0B, "Nanya Technology" },
581 	{ 0x8C, "Elite Flash Storage" },
582 	{ 0x0D, "Mysticom" },
583 	{ 0x0E, "LightSand Communications" },
584 	{ 0x8F, "ATI Technologies" },
585 	{ 0x10, "Agere Systems" },
586 	{ 0x91, "NeoMagic" },
587 	{ 0x92, "AuroraNetics" },
588 	{ 0x13, "Golden Empire" },
589 	{ 0x94, "Muskin" },
590 	{ 0x15, "Tioga Technologies" },
591 	{ 0x16, "Netlist" },
592 	{ 0x97, "TeraLogic" },
593 	{ 0x98, "Cicada Semiconductor" },
594 	{ 0x19, "Centon Electronics" },
595 	{ 0x1A, "Tyco Electronics" },
596 	{ 0x9B, "Magis Works" },
597 	{ 0x1C, "Zettacom" },
598 	{ 0x9D, "Cogency Semiconductor" },
599 	{ 0x9E, "Chipcon AS" },
600 	{ 0x1F, "Aspex Technology" },
601 	{ 0x20, "F5 Networks" },
602 	{ 0xA1, "Programmable Silicon Solutions" },
603 	{ 0xA2, "ChipWrights" },
604 	{ 0x23, "Acorn Networks" },
605 	{ 0xA4, "Quicklogic" },
606 	{ 0x25, "Kingmax Semiconductor" },
607 	{ 0x26, "BOPS" },
608 	{ 0xA7, "Flasys" },
609 	{ 0xA8, "BitBlitz Communications" },
610 	{ 0x29, "eMemory Technology" },
611 	{ 0x2A, "Procket Networks" },
612 	{ 0xAB, "Purple Ray" },
613 	{ 0x2C, "Trebia Networks" },
614 	{ 0xAD, "Delta Electronics" },
615 	{ 0xAE, "Onex Communications" },
616 	{ 0x2F, "Ample Communications" },
617 	{ 0xB0, "Memory Experts Intl" },
618 	{ 0x31, "Astute Networks" },
619 	{ 0x32, "Azanda Network Devices" },
620 	{ 0xB3, "Dibcom" },
621 	{ 0x34, "Tekmos" },
622 	{ 0xB5, "API NetWorks" },
623 	{ 0xB6, "Bay Microsystems" },
624 	{ 0x37, "Firecron Ltd" },
625 	{ 0x38, "Resonext Communications" },
626 	{ 0xB9, "Tachys Technologies" },
627 	{ 0xBA, "Equator Technology" },
628 	{ 0x3B, "Concept Computer" },
629 	{ 0xBC, "SILCOM" },
630 	{ 0x3D, "3Dlabs" },
631 	{ 0x3E, "ct Magazine" },
632 	{ 0xBF, "Sanera Systems" },
633 	{ 0x40, "Silicon Packets" },
634 	{ 0xC1, "Viasystems Group" },
635 	{ 0xC2, "Simtek" },
636 	{ 0x43, "Semicon Devices Singapore" },
637 	{ 0xC4, "Satron Handelsges" },
638 	{ 0x45, "Improv Systems" },
639 	{ 0x46, "INDUSYS GmbH" },
640 	{ 0xC7, "Corrent" },
641 	{ 0xC8, "Infrant Technologies" },
642 	{ 0x49, "Ritek Corp" },
643 	{ 0x4A, "empowerTel Networks" },
644 	{ 0xCB, "Hypertec" },
645 	{ 0x4C, "Cavium Networks" },
646 	{ 0xCD, "PLX Technology" },
647 	{ 0xCE, "Massana Design" },
648 	{ 0x4F, "Intrinsity" },
649 	{ 0xD0, "Valence Semiconductor" },
650 	{ 0x51, "Terawave Communications" },
651 	{ 0x52, "IceFyre Semiconductor" },
652 	{ 0xD3, "Primarion" },
653 	{ 0x54, "Picochip Designs Ltd" },
654 	{ 0xD5, "Silverback Systems" },
655 	{ 0xD6, "Jade Star Technologies" },
656 	{ 0x57, "Pijnenburg Securealink" },
657 	{ 0x58, "MemorySolutioN" },
658 	{ 0xD9, "Cambridge Silicon Radio" },
659 	{ 0xDA, "Swissbit" },
660 	{ 0x5B, "Nazomi Communications" },
661 	{ 0xDC, "eWave System" },
662 	{ 0x5D, "Rockwell Collins" },
663 	{ 0x5E, "PAION" },
664 	{ 0xDF, "Alphamosaic Ltd" },
665 	{ 0xE0, "Sandburst" },
666 	{ 0x61, "SiCon Video" },
667 	{ 0x62, "NanoAmp Solutions" },
668 	{ 0xE3, "Ericsson Technology" },
669 	{ 0x64, "PrairieComm" },
670 	{ 0xE5, "Mitac International" },
671 	{ 0xE6, "Layer N Networks" },
672 	{ 0x67, "Atsana Semiconductor" },
673 	{ 0x68, "Allegro Networks" },
674 	{ 0xE9, "Marvell Semiconductors" },
675 	{ 0xEA, "Netergy Microelectronic" },
676 	{ 0x6B, "NVIDIA" },
677 	{ 0xEC, "Internet Machines" },
678 	{ 0x6D, "Peak Electronics" },
679 	{ 0xEF, "Accton Technology" },
680 	{ 0x70, "Teradiant Networks" },
681 	{ 0xF1, "Europe Technologies" },
682 	{ 0xF2, "Cortina Systems" },
683 	{ 0x73, "RAM Components" },
684 	{ 0xF4, "Raqia Networks" },
685 	{ 0x75, "ClearSpeed" },
686 	{ 0x76, "Matsushita Battery" },
687 	{ 0xF7, "Xelerated" },
688 	{ 0xF8, "SimpleTech" },
689 	{ 0x79, "Utron Technology" },
690 	{ 0x7A, "Astec International" },
691 	{ 0xFB, "AVM gmbH" },
692 	{ 0x7C, "Redux Communications" },
693 	{ 0xFD, "Dot Hill Systems" },
694 	{ 0xFE, "TeraChip" },
695 	{ 0x00, NULL },
696 };
697 
698 const struct valstr jedec_id5_vals[] = {
699 	{ 0x01, "T-RAM Incorporated" },
700 	{ 0x02, "Innovics Wireless" },
701 	{ 0x83, "Teknovus" },
702 	{ 0x04, "KeyEye Communications" },
703 	{ 0x85, "Runcom Technologies" },
704 	{ 0x86, "RedSwitch" },
705 	{ 0x07, "Dotcast" },
706 	{ 0x08, "Silicon Mountain Memory" },
707 	{ 0x89, "Signia Technologies" },
708 	{ 0x8A, "Pixim" },
709 	{ 0x0B, "Galazar Networks" },
710 	{ 0x8C, "White Electronic Designs" },
711 	{ 0x0D, "Patriot Scientific" },
712 	{ 0x0E, "Neoaxiom Corporation" },
713 	{ 0x8F, "3Y Power Technology" },
714 	{ 0x10, "Europe Technologies" },
715 	{ 0x91, "Potentia Power Systems" },
716 	{ 0x92, "C-guys Incorporated" },
717 	{ 0x13, "Digital Communications Technology Incorporated" },
718 	{ 0x94, "Silicon-Based Technology" },
719 	{ 0x15, "Fulcrum Microsystems" },
720 	{ 0x16, "Positivo Informatica Ltd" },
721 	{ 0x97, "XIOtech Corporation" },
722 	{ 0x98, "PortalPlayer" },
723 	{ 0x19, "Zhiying Software" },
724 	{ 0x1A, "Direct2Data" },
725 	{ 0x9B, "Phonex Broadband" },
726 	{ 0x1C, "Skyworks Solutions" },
727 	{ 0x9D, "Entropic Communications" },
728 	{ 0x9E, "Pacific Force Technology" },
729 	{ 0x1F, "Zensys A/S" },
730 	{ 0x20, "Legend Silicon Corp." },
731 	{ 0xA1, "sci-worx GmbH" },
732 	{ 0xA2, "Oasis Silicon Systems" },
733 	{ 0x23, "Renesas Technology" },
734 	{ 0xA4, "Raza Microelectronics" },
735 	{ 0x25, "Phyworks" },
736 	{ 0x26, "MediaTek" },
737 	{ 0xA7, "Non-cents Productions" },
738 	{ 0xA8, "US Modular" },
739 	{ 0x29, "Wintegra Ltd" },
740 	{ 0x2A, "Mathstar" },
741 	{ 0xAB, "StarCore" },
742 	{ 0x2C, "Oplus Technologies" },
743 	{ 0xAD, "Mindspeed" },
744 	{ 0xAE, "Just Young Computer" },
745 	{ 0x2F, "Radia Communications" },
746 	{ 0xB0, "OCZ" },
747 	{ 0x31, "Emuzed" },
748 	{ 0x32, "LOGIC Devices" },
749 	{ 0xB3, "Inphi Corporation" },
750 	{ 0x34, "Quake Technologies" },
751 	{ 0xB5, "Vixel" },
752 	{ 0xB6, "SolusTek" },
753 	{ 0x37, "Kongsberg Maritime" },
754 	{ 0x38, "Faraday Technology" },
755 	{ 0xB9, "Altium Ltd." },
756 	{ 0xBA, "Insyte" },
757 	{ 0x3B, "ARM Ltd." },
758 	{ 0xBC, "DigiVision" },
759 	{ 0x3D, "Vativ Technologies" },
760 	{ 0x3E, "Endicott Interconnect Technologies" },
761 	{ 0xBF, "Pericom" },
762 	{ 0x40, "Bandspeed" },
763 	{ 0xC1, "LeWiz Communications" },
764 	{ 0xC2, "CPU Technology" },
765 	{ 0x43, "Ramaxel Technology" },
766 	{ 0xC4, "DSP Group" },
767 	{ 0x45, "Axis Communications" },
768 	{ 0x46, "Legacy Electronics" },
769 	{ 0xC7, "Chrontel" },
770 	{ 0xC8, "Powerchip Semiconductor" },
771 	{ 0x49, "MobilEye Technologies" },
772 	{ 0x4A, "Excel Semiconductor" },
773 	{ 0xCB, "A-DATA Technology" },
774 	{ 0x4C, "VirtualDigm" },
775 	{ 0x00, NULL },
776 };
777 
778 int
779 ipmi_spd_print(uint8_t *spd_data, int len)
780 {
781 	int k = 0;
782 	int ii = 0;
783 
784 	if (len < 92)
785 		return -1; /* we need first 91 bytes to do our thing */
786 
787 	printf(" Memory Type           : %s\n",
788 	       val2str(spd_data[2], spd_memtype_vals));
789 
790 	if (spd_data[2] == 0x0B)	/* DDR3 SDRAM */
791 	{
792 		int iPN;
793 		char *pchPN = spd_data+128;
794 		int sdram_cap = 0;
795 		int pri_bus_width = 0;
796 		int sdram_width = 0;
797 		int ranks = 0;
798 		int mem_size = 0;
799 
800 		if (len < 148)
801 			return -1; /* we need first 91 bytes to do our thing */
802 
803 
804 		sdram_cap = ldexp(256,(spd_data[4]&15));
805 		pri_bus_width = ldexp(8,(spd_data[8]&7));
806 		sdram_width = ldexp(4,(spd_data[7]&7));
807 		ranks = ldexp(1,((spd_data[7]&0x3F)>>3));
808 		mem_size = (sdram_cap/8) * (pri_bus_width/sdram_width) * ranks;
809 		printf(" SDRAM Capacity        : %d MB\n", sdram_cap );
810 		printf(" Memory Banks          : %s\n", val2str(spd_data[4]>>4, ddr3_banks_vals));
811 		printf(" Primary Bus Width     : %d bits\n", pri_bus_width );
812 		printf(" SDRAM Device Width    : %d bits\n", sdram_width );
813 		printf(" Number of Ranks       : %d\n", ranks );
814 		printf(" Memory size           : %d MB\n", mem_size );
815 
816 		/* printf(" Memory Density        : %s\n", val2str(spd_data[4]&15, ddr3_density_vals)); */
817 		printf(" 1.5 V Nominal Op      : %s\n", (((spd_data[6]&1) != 0) ? "No":"Yes" ) );
818 		printf(" 1.35 V Nominal Op     : %s\n", (((spd_data[6]&2) != 0) ? "No":"Yes" ) );
819 		printf(" 1.2X V Nominal Op     : %s\n", (((spd_data[6]&4) != 0) ? "No":"Yes" ) );
820 		printf(" Error Detect/Cor      : %s\n", val2str(spd_data[8]>>3, ddr3_ecc_vals));
821 
822 		printf(" Manufacturer          : ");
823 		switch (spd_data[117]&127)
824 		{
825 		case	0:
826 			printf("%s\n", val2str(spd_data[118], jedec_id1_vals));
827 			break;
828 
829 		case	1:
830 			printf("%s\n", val2str(spd_data[118], jedec_id2_vals));
831 			break;
832 
833 		case	2:
834 			printf("%s\n", val2str(spd_data[118], jedec_id3_vals));
835 			break;
836 
837 		case	3:
838 			printf("%s\n", val2str(spd_data[118], jedec_id4_vals));
839 			break;
840 
841 		case	4:
842 			printf("%s\n", val2str(spd_data[118], jedec_id5_vals));
843 			break;
844 
845 		default:
846 			printf("%s\n", "JEDEC JEP106 update required" );
847 
848 		}
849 
850 		printf(" Manufacture Date      : year %c%c week %c%c\n",
851 		'0'+(spd_data[120]>>4), '0'+(spd_data[120]&15), '0'+(spd_data[121]>>4), '0'+(spd_data[121]&15) );
852 
853 		printf(" Serial Number         : %02x%02x%02x%02x\n",
854 		spd_data[122], spd_data[123], spd_data[124], spd_data[125]);
855 
856 		printf(" Part Number           : ");
857 		for (iPN=0; iPN < 19; iPN++)
858 		{
859 			printf( "%c", *pchPN++ );
860 		}
861 		printf("\n");
862 	} else if (spd_data[2] == 0x0C)	/* DDR4 SDRAM */
863 	{
864 		int i;
865 		int sdram_cap = 0;
866 		int pri_bus_width = 0;
867 		int sdram_width = 0;
868 		int mem_size = 0;
869 		int lrank_dimm;
870 		uint32_t year;
871 		uint32_t week;
872 
873 		if (len < 348)
874 			return -1;
875 
876 		/* "Logical rank" referes to the individually addressable die
877 		 * in a 3DS stack and has no meaning for monolithic or
878 		 * multi-load stacked SDRAMs; however, for the purposes of
879 		 * calculating the capacity of the module, one should treat
880 		 * monolithic and multi-load stack SDRAMs as having one logical
881 		 * rank per package rank.
882 		 */
883 		lrank_dimm = (spd_data[12]>>3&0x3) + 1; /* Number of Package Ranks per DIMM */
884 		if ((spd_data[6] & 0x3) == 0x2) { /* 3DS package Type */
885 			lrank_dimm *= ((spd_data[6]>>4)&0x3) + 1; /* Die Count */
886 		}
887 		sdram_cap = ldexp(256,(spd_data[4]&15));
888 		pri_bus_width = ldexp(8,(spd_data[13]&7));
889 		sdram_width = ldexp(4,(spd_data[12]&7));
890 		mem_size = (sdram_cap/8) * (pri_bus_width/sdram_width) * lrank_dimm;
891 		printf(" SDRAM Package Type    : %s\n", val2str((spd_data[6]>>7), ddr4_package_type));
892 		printf(" Technology            : %s\n", val2str((spd_data[3]&15), ddr4_technology_type));
893 		printf(" SDRAM Die Count       : %d\n", ((spd_data[6]>>4) & 3)+1);
894 		printf(" SDRAM Capacity        : %d Mb\n", sdram_cap );
895 		printf(" Memory Bank Group     : %s\n", val2str((spd_data[4]>>6 & 0x3), ddr4_bank_groups));
896 		printf(" Memory Banks          : %s\n", val2str((spd_data[4]>>4 & 0x3), ddr4_banks_vals));
897 		printf(" Primary Bus Width     : %d bits\n", pri_bus_width );
898 		printf(" SDRAM Device Width    : %d bits\n", sdram_width );
899 		printf(" Logical Rank per DIMM : %d\n", lrank_dimm );
900 		printf(" Memory size           : %d MB\n", mem_size );
901 
902 		printf(" Memory Density        : %s\n", val2str(spd_data[4]&15, ddr4_density_vals));
903 		printf(" 1.2 V Nominal Op      : %s\n", (((spd_data[11]&3) != 3) ? "No":"Yes" ) );
904 		printf(" TBD1 V Nominal Op     : %s\n", (((spd_data[11]>>2&3) != 3) ? "No":"Yes" ) );
905 		printf(" TBD2 V Nominal Op     : %s\n", (((spd_data[11]>>4&3) != 3) ? "No":"Yes" ) );
906 		printf(" Error Detect/Cor      : %s\n", val2str(spd_data[13]>>3, ddr4_ecc_vals));
907 
908 		printf(" Manufacturer          : ");
909 		switch (spd_data[320]&127)
910 		{
911 		case	0:
912 			printf("%s\n", val2str(spd_data[321], jedec_id1_vals));
913 			break;
914 
915 		case	1:
916 			printf("%s\n", val2str(spd_data[321], jedec_id2_vals));
917 			break;
918 
919 		case	2:
920 			printf("%s\n", val2str(spd_data[321], jedec_id3_vals));
921 			break;
922 
923 		case	3:
924 			printf("%s\n", val2str(spd_data[321], jedec_id4_vals));
925 			break;
926 
927 		case	4:
928 			printf("%s\n", val2str(spd_data[321], jedec_id5_vals));
929 			break;
930 
931 		default:
932 			printf("%s\n", "JEDEC JEP106 update required");
933 
934 		}
935 
936 		year = ((spd_data[323] >> 4) * 10) + (spd_data[323] & 15);
937 		week = ((spd_data[324]>>4) * 10) + (spd_data[324] & 15);
938 		printf(" Manufacture Date      : year %4d week %2d\n",
939 		       2000 + year, week);
940 
941 		printf(" Serial Number         : %02x%02x%02x%02x\n",
942 		spd_data[325], spd_data[326], spd_data[327], spd_data[328]);
943 
944 		printf(" Part Number           : ");
945 		for (i=329; i <= 348; i++)
946 		{
947 			printf( "%c", spd_data[i]);
948 		}
949 		printf("\n");
950 	}
951 	else
952 	{
953 		if (len < 100) {
954 			return (-1);
955 		}
956 		ii = (spd_data[3] & 0x0f) + (spd_data[4] & 0x0f) - 17;
957 		k = ((spd_data[5] & 0x7) + 1) * spd_data[17];
958 
959 		if(ii > 0 && ii <= 12 && k > 0) {
960 			printf(" Memory Size           : %d MB\n", ((1 << ii) * k));
961 		} else {
962 			printf(" Memory Size    INVALID: %d, %d, %d, %d\n", spd_data[3],
963 					spd_data[4], spd_data[5], spd_data[17]);
964 		}
965 		printf(" Voltage Intf          : %s\n",
966 		val2str(spd_data[8], spd_voltage_vals));
967 		printf(" Error Detect/Cor      : %s\n",
968 		val2str(spd_data[11], spd_config_vals));
969 
970 		/* handle jedec table bank continuation values */
971 		printf(" Manufacturer          : ");
972 		if (spd_data[64] != 0x7f)
973 			printf("%s\n",
974 			val2str(spd_data[64], jedec_id1_vals));
975 		else {
976 			if (spd_data[65] != 0x7f)
977 				printf("%s\n",
978 				val2str(spd_data[65], jedec_id2_vals));
979 			else {
980 				if (spd_data[66] != 0x7f)
981 					printf("%s\n",
982 					val2str(spd_data[66], jedec_id3_vals));
983 				else {
984 					if (spd_data[67] != 0x7f)
985 						printf("%s\n",
986 						val2str(spd_data[67],
987 							jedec_id4_vals));
988 					else
989 						printf("%s\n",
990 						val2str(spd_data[68],
991 							jedec_id5_vals));
992 				}
993 			}
994 		}
995 
996 		if (spd_data[73]) {
997 			char part[19];
998 			memcpy(part, spd_data+73, 18);
999 			part[18] = 0;
1000 			printf(" Part Number           : %s\n", part);
1001 		}
1002 
1003 		printf(" Serial Number         : %02x%02x%02x%02x\n",
1004 		spd_data[95], spd_data[96], spd_data[97], spd_data[98]);
1005 	}
1006 
1007 	if (verbose) {
1008 		printf("\n");
1009 		printbuf(spd_data, len, "SPD DATA");
1010 	}
1011 
1012 	return 0;
1013 }
1014 
1015 int
1016 ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id)
1017 {
1018 	struct ipmi_rs * rsp;
1019 	struct ipmi_rq req;
1020 	struct fru_info fru;
1021 	uint8_t *spd_data, msg_data[4];
1022 	int len, offset;
1023 
1024 	msg_data[0] = id;
1025 
1026 	memset(&req, 0, sizeof(req));
1027 	req.msg.netfn = IPMI_NETFN_STORAGE;
1028 	req.msg.cmd = GET_FRU_INFO;
1029 	req.msg.data = msg_data;
1030 	req.msg.data_len = 1;
1031 
1032 	rsp = intf->sendrecv(intf, &req);
1033 	if (rsp == NULL) {
1034 		printf(" Device not present (No Response)\n");
1035 		return -1;
1036 	}
1037 	if (rsp->ccode > 0) {
1038 		printf(" Device not present (%s)\n",
1039 		       val2str(rsp->ccode, completion_code_vals));
1040 		return -1;
1041 	}
1042 
1043 	fru.size = (rsp->data[1] << 8) | rsp->data[0];
1044 	fru.access = rsp->data[2] & 0x1;
1045 
1046 	lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
1047 		fru.size, fru.access ? "words" : "bytes");
1048 
1049 
1050 	if (fru.size < 1) {
1051 		lprintf(LOG_ERR, " Invalid FRU size %d", fru.size);
1052 		return -1;
1053 	}
1054 
1055         spd_data = malloc(fru.size);
1056 
1057         if (spd_data == NULL) {
1058 		printf(" Unable to malloc memory for spd array of size=%d\n",
1059 		       fru.size);
1060 		return -1;
1061         }
1062 
1063 	memset(&req, 0, sizeof(req));
1064 	req.msg.netfn = IPMI_NETFN_STORAGE;
1065 	req.msg.cmd = GET_FRU_DATA;
1066 	req.msg.data = msg_data;
1067 	req.msg.data_len = 4;
1068 
1069 	offset = 0;
1070 	memset(spd_data, 0, fru.size);
1071 	do {
1072 		msg_data[0] = id;
1073 		msg_data[1] = offset & 0xFF;
1074 		msg_data[2] = offset >> 8;
1075 		msg_data[3] = FRU_DATA_RQST_SIZE;
1076 
1077 		rsp = intf->sendrecv(intf, &req);
1078 		if (rsp == NULL) {
1079 			printf(" Device not present (No Response)\n");
1080                         free(spd_data);
1081                         spd_data = NULL;
1082 			return -1;
1083 		}
1084 		if (rsp->ccode > 0) {
1085 			printf(" Device not present (%s)\n",
1086 			       val2str(rsp->ccode, completion_code_vals));
1087 
1088                         free(spd_data);
1089                         spd_data = NULL;
1090 			/* Timeouts are acceptable. No DIMM in the socket */
1091 			if (rsp->ccode == 0xc3)
1092 				return 1;
1093 
1094 			return -1;
1095 		}
1096 
1097 		len = rsp->data[0];
1098 		memcpy(&spd_data[offset], rsp->data + 1, len);
1099 		offset += len;
1100 	} while (offset < fru.size);
1101 
1102 	/* now print spd info */
1103 	ipmi_spd_print(spd_data, offset);
1104         free(spd_data);
1105         spd_data = NULL;
1106 
1107 	return 0;
1108 }
1109