xref: /openbmc/ipmitool/lib/ipmi_ekanalyzer.c (revision 2d79e69f)
1c18ec02fSPetter Reinholdtsen /*
2c18ec02fSPetter Reinholdtsen  * Copyright (c) 2007 Kontron Canada, Inc.  All Rights Reserved.
3c18ec02fSPetter Reinholdtsen  *
4c18ec02fSPetter Reinholdtsen  * Base on code from
5c18ec02fSPetter Reinholdtsen  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
6c18ec02fSPetter Reinholdtsen  *
7c18ec02fSPetter Reinholdtsen  * Redistribution and use in source and binary forms, with or without
8c18ec02fSPetter Reinholdtsen  * modification, are permitted provided that the following conditions
9c18ec02fSPetter Reinholdtsen  * are met:
10c18ec02fSPetter Reinholdtsen  *
11c18ec02fSPetter Reinholdtsen  * Redistribution of source code must retain the above copyright
12c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer.
13c18ec02fSPetter Reinholdtsen  *
14c18ec02fSPetter Reinholdtsen  * Redistribution in binary form must reproduce the above copyright
15c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer in the
16c18ec02fSPetter Reinholdtsen  * documentation and/or other materials provided with the distribution.
17c18ec02fSPetter Reinholdtsen  *
18c18ec02fSPetter Reinholdtsen  * Neither the name of Sun Microsystems, Inc. or the names of
19c18ec02fSPetter Reinholdtsen  * contributors may be used to endorse or promote products derived
20c18ec02fSPetter Reinholdtsen  * from this software without specific prior written permission.
21c18ec02fSPetter Reinholdtsen  *
22c18ec02fSPetter Reinholdtsen  * This software is provided "AS IS," without a warranty of any kind.
23c18ec02fSPetter Reinholdtsen  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
24c18ec02fSPetter Reinholdtsen  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
25c18ec02fSPetter Reinholdtsen  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
26c18ec02fSPetter Reinholdtsen  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
27c18ec02fSPetter Reinholdtsen  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
28c18ec02fSPetter Reinholdtsen  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
29c18ec02fSPetter Reinholdtsen  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
30c18ec02fSPetter Reinholdtsen  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
31c18ec02fSPetter Reinholdtsen  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
32c18ec02fSPetter Reinholdtsen  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
33c18ec02fSPetter Reinholdtsen  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34c18ec02fSPetter Reinholdtsen  */
35c18ec02fSPetter Reinholdtsen 
36c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_ekanalyzer.h>
37c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
38c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
39c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_strings.h>
40c18ec02fSPetter Reinholdtsen 
41c18ec02fSPetter Reinholdtsen #include <stdlib.h>
42c18ec02fSPetter Reinholdtsen #include <string.h>
43c18ec02fSPetter Reinholdtsen #include <time.h>
44c18ec02fSPetter Reinholdtsen 
45c18ec02fSPetter Reinholdtsen #define NO_MORE_INFO_FIELD         0xc1
46c18ec02fSPetter Reinholdtsen #define TYPE_CODE 0xc0 /*Language code*/
47c18ec02fSPetter Reinholdtsen 
48b37b9149SZdenek Styblik /*
49c18ec02fSPetter Reinholdtsen  * CONSTANT
50b37b9149SZdenek Styblik  */
51c18ec02fSPetter Reinholdtsen const int ERROR_STATUS  = -1;
52c18ec02fSPetter Reinholdtsen const int OK_STATUS     = 0;
53c18ec02fSPetter Reinholdtsen 
54c18ec02fSPetter Reinholdtsen const char * STAR_LINE_LIMITER =
55c18ec02fSPetter Reinholdtsen             "*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*";
56c18ec02fSPetter Reinholdtsen const char * EQUAL_LINE_LIMITER =
57c18ec02fSPetter Reinholdtsen             "=================================================================";
58c18ec02fSPetter Reinholdtsen const int SIZE_OF_FILE_TYPE          = 3;
59c18ec02fSPetter Reinholdtsen const unsigned char AMC_MODULE       = 0x80;
60c18ec02fSPetter Reinholdtsen const int PICMG_ID_OFFSET            = 3;
61c18ec02fSPetter Reinholdtsen const unsigned int COMPARE_CANDIDATE = 2;
62c18ec02fSPetter Reinholdtsen /* In AMC.0 or PICMG 3.0 specification offset start from 0 with 3 bytes of
63c18ec02fSPetter Reinholdtsen  * Mfg.ID, 1 byte of Picmg record Id, and
64c18ec02fSPetter Reinholdtsen  * 1 byte of format version, so the data offset start from 5
65c18ec02fSPetter Reinholdtsen  */
66c18ec02fSPetter Reinholdtsen const int START_DATA_OFFSET         = 5;
67c18ec02fSPetter Reinholdtsen const int LOWER_OEM_TYPE            = 0xf0;
68c18ec02fSPetter Reinholdtsen const int UPPER_OEM_TYPE            = 0xfe;
69c18ec02fSPetter Reinholdtsen const unsigned char DISABLE_PORT    = 0x1f;
70c18ec02fSPetter Reinholdtsen 
71c18ec02fSPetter Reinholdtsen const struct valstr ipmi_ekanalyzer_module_type[] = {
72c18ec02fSPetter Reinholdtsen    { ON_CARRIER_FRU_FILE,     "On-Carrier Device" },
73c18ec02fSPetter Reinholdtsen    { A1_AMC_FRU_FILE,         "AMC slot A1" },
74c18ec02fSPetter Reinholdtsen    { A2_AMC_FRU_FILE,         "AMC slot A2" },
75c18ec02fSPetter Reinholdtsen    { A3_AMC_FRU_FILE,         "AMC slot A3" },
76c18ec02fSPetter Reinholdtsen    { A4_AMC_FRU_FILE,         "AMC slot A4" },
77c18ec02fSPetter Reinholdtsen    { B1_AMC_FRU_FILE,         "AMC slot B1" },
78c18ec02fSPetter Reinholdtsen    { B2_AMC_FRU_FILE,         "AMC slot B2" },
79c18ec02fSPetter Reinholdtsen    { B3_AMC_FRU_FILE,         "AMC slot B3" },
80c18ec02fSPetter Reinholdtsen    { B4_AMC_FRU_FILE,         "AMC slot B4" },
81c18ec02fSPetter Reinholdtsen    { RTM_FRU_FILE,            "RTM" }, /*This is OEM specific module*/
82c18ec02fSPetter Reinholdtsen    { CONFIG_FILE,             "Configuration file" },
83c18ec02fSPetter Reinholdtsen    { SHELF_MANAGER_FRU_FILE,  "Shelf Manager" },
84c18ec02fSPetter Reinholdtsen    { 0xffff ,                 NULL },
85c18ec02fSPetter Reinholdtsen };
86c18ec02fSPetter Reinholdtsen 
87c18ec02fSPetter Reinholdtsen const struct valstr ipmi_ekanalyzer_IPMBL_addr[] = {
88c18ec02fSPetter Reinholdtsen    { 0x72,         "AMC slot A1" },
89c18ec02fSPetter Reinholdtsen    { 0x74,         "AMC slot A2" },
90c18ec02fSPetter Reinholdtsen    { 0x76,         "AMC slot A3" },
91c18ec02fSPetter Reinholdtsen    { 0x78,         "AMC slot A4" },
92c18ec02fSPetter Reinholdtsen    { 0x7a,         "AMC slot B1" },
93c18ec02fSPetter Reinholdtsen    { 0x7c,         "AMC slot B2" },
94c18ec02fSPetter Reinholdtsen    { 0x7e,         "AMC slot B3" },
95c18ec02fSPetter Reinholdtsen    { 0x80,         "AMC slot B4" },
96c18ec02fSPetter Reinholdtsen    { 0x90,         "RTM"}, /*This is OEM specific module*/
97c18ec02fSPetter Reinholdtsen    { 0xffff ,      NULL },
98c18ec02fSPetter Reinholdtsen };
99c18ec02fSPetter Reinholdtsen 
100c18ec02fSPetter Reinholdtsen const struct valstr ipmi_ekanalyzer_link_type[] = {
101c18ec02fSPetter Reinholdtsen    { 0x00,         "Reserved" },
102c18ec02fSPetter Reinholdtsen    { 0x01,         "Reserved" },
103c18ec02fSPetter Reinholdtsen    { 0x02,         "AMC.1 PCI Express" },
104c18ec02fSPetter Reinholdtsen    { 0x03,         "AMC.1 PCI Express Advanced Switching" },
105c18ec02fSPetter Reinholdtsen    { 0x04,         "AMC.1 PCI Express Advanced Switching" },
106c18ec02fSPetter Reinholdtsen    { 0x05,         "AMC.2 Ethernet" },
107c18ec02fSPetter Reinholdtsen    { 0x06,         "AMC.4 Serial RapidIO" },
108c18ec02fSPetter Reinholdtsen    { 0x07,         "AMC.3 Storage" },
109c18ec02fSPetter Reinholdtsen    /*This is OEM specific module*/
110c18ec02fSPetter Reinholdtsen    { 0xf0,         "OEM Type 0"},
111c18ec02fSPetter Reinholdtsen    { 0xf1,         "OEM Type 1"},
112c18ec02fSPetter Reinholdtsen    { 0xf2,         "OEM Type 2"},
113c18ec02fSPetter Reinholdtsen    { 0xf3,         "OEM Type 3"},
114c18ec02fSPetter Reinholdtsen    { 0xf4,         "OEM Type 4"},
115c18ec02fSPetter Reinholdtsen    { 0xf5,         "OEM Type 5"},
116c18ec02fSPetter Reinholdtsen    { 0xf6,         "OEM Type 6"},
117c18ec02fSPetter Reinholdtsen    { 0xf7,         "OEM Type 7"},
118c18ec02fSPetter Reinholdtsen    { 0xf8,         "OEM Type 8"},
119c18ec02fSPetter Reinholdtsen    { 0xf9,         "OEM Type 9"},
120c18ec02fSPetter Reinholdtsen    { 0xfa,         "OEM Type 10"},
121c18ec02fSPetter Reinholdtsen    { 0xfb,         "OEM Type 11"},
122c18ec02fSPetter Reinholdtsen    { 0xfc,         "OEM Type 12"},
123c18ec02fSPetter Reinholdtsen    { 0xfd,         "OEM Type 13"},
124c18ec02fSPetter Reinholdtsen    { 0xfe,         "OEM Type 14"},
125c18ec02fSPetter Reinholdtsen    { 0xff ,        "Reserved" },
126c18ec02fSPetter Reinholdtsen };
127c18ec02fSPetter Reinholdtsen 
128c18ec02fSPetter Reinholdtsen /*Reference: AMC.1 specification*/
129c18ec02fSPetter Reinholdtsen const struct valstr ipmi_ekanalyzer_extension_PCIE[] = {
130c18ec02fSPetter Reinholdtsen    { 0x00,         "Gen 1 capable - non SSC" },
131c18ec02fSPetter Reinholdtsen    { 0x01,         "Gen 1 capable - SSC" },
132c18ec02fSPetter Reinholdtsen    { 0x02,         "Gen 2 capable - non SSC" },
133c18ec02fSPetter Reinholdtsen    { 0x03,         "Gen 3 capable - SSC" },
134c18ec02fSPetter Reinholdtsen    { 0x0f,         "Reserved"},
135c18ec02fSPetter Reinholdtsen };
136c18ec02fSPetter Reinholdtsen /*Reference: AMC.2 specification*/
137c18ec02fSPetter Reinholdtsen const struct valstr ipmi_ekanalyzer_extension_ETHERNET[] = {
138c18ec02fSPetter Reinholdtsen    { 0x00,         "1000BASE-BX (SerDES Gigabit) Ethernet link" },
139c18ec02fSPetter Reinholdtsen    { 0x01,         "10GBASE-BX4 10 Gigabit Ethernet link" },
140c18ec02fSPetter Reinholdtsen };
141c18ec02fSPetter Reinholdtsen /*Reference: AMC.3 specification*/
142c18ec02fSPetter Reinholdtsen const struct valstr ipmi_ekanalyzer_extension_STORAGE[] = {
143c18ec02fSPetter Reinholdtsen    { 0x00,         "Fibre Channel  (FC)" },
144c18ec02fSPetter Reinholdtsen    { 0x01,         "Serial ATA (SATA)" },
145c18ec02fSPetter Reinholdtsen    { 0x02,         "Serial Attached SCSI (SAS/SATA)" },
146c18ec02fSPetter Reinholdtsen };
147c18ec02fSPetter Reinholdtsen 
148c18ec02fSPetter Reinholdtsen const struct valstr ipmi_ekanalyzer_asym_PCIE[] = {
149c18ec02fSPetter Reinholdtsen    { 0x00,         "exact match"},
150c18ec02fSPetter Reinholdtsen    { 0x01,         "provides a Primary PCI Express Port" },
151c18ec02fSPetter Reinholdtsen    { 0x02,         "provides a Secondary PCI Express Port" },
152c18ec02fSPetter Reinholdtsen };
153c18ec02fSPetter Reinholdtsen 
154c18ec02fSPetter Reinholdtsen const struct valstr ipmi_ekanalyzer_asym_STORAGE[] = {
155c18ec02fSPetter Reinholdtsen    { 0x00,         "FC or SAS interface {exact match}" },
156c18ec02fSPetter Reinholdtsen    { 0x01,         "SATA Server interface" },
157c18ec02fSPetter Reinholdtsen    { 0x02,         "SATA Client interface" },
158c18ec02fSPetter Reinholdtsen    { 0x03,         "Reserved" },
159c18ec02fSPetter Reinholdtsen };
160c18ec02fSPetter Reinholdtsen 
161c18ec02fSPetter Reinholdtsen const struct valstr ipmi_ekanalyzer_picmg_record_id[] = {
162c18ec02fSPetter Reinholdtsen    { 0x04,         "Backplane Point to Point Connectivity Record" },
163c18ec02fSPetter Reinholdtsen    { 0x10,         "Address Table Record" },
164c18ec02fSPetter Reinholdtsen    { 0x11,         "Shelf Power Distribution Record" },
165c18ec02fSPetter Reinholdtsen    { 0x12,         "Shelf Activation and Power Management Record" },
166c18ec02fSPetter Reinholdtsen    { 0x13,         "Shelf Manager IP Connection Record" },
167c18ec02fSPetter Reinholdtsen    { 0x14,         "Board Point to Point Connectivity Record" },
168c18ec02fSPetter Reinholdtsen    { 0x15,         "Radial IPMB-0 Link Mapping Record" },
169c18ec02fSPetter Reinholdtsen    { 0x16,         "Module Current Requirements Record" },
170c18ec02fSPetter Reinholdtsen    { 0x17,         "Carrier Activation and Power Management Record" },
171c18ec02fSPetter Reinholdtsen    { 0x18,         "Carrier Point-to-Point Connectivity Record" },
172c18ec02fSPetter Reinholdtsen    { 0x19,         "AdvancedMC Point-to-Point Connectivity Record" },
173c18ec02fSPetter Reinholdtsen    { 0x1a,         "Carrier Information Table" },
174c18ec02fSPetter Reinholdtsen    { 0x1b,         "Shelf Fan Geography Record" },
175c18ec02fSPetter Reinholdtsen    { 0x2c,         "Carrier Clock Point-to-Point Connectivity Record" },
176c18ec02fSPetter Reinholdtsen    { 0x2d,         "Clock Configuration Record" },
177c18ec02fSPetter Reinholdtsen };
178c18ec02fSPetter Reinholdtsen 
179c18ec02fSPetter Reinholdtsen extern int verbose;
180c18ec02fSPetter Reinholdtsen 
181c18ec02fSPetter Reinholdtsen struct ipmi_ek_multi_header {
182c18ec02fSPetter Reinholdtsen    struct fru_multirec_header header;
183c18ec02fSPetter Reinholdtsen    unsigned char * data;
184c18ec02fSPetter Reinholdtsen    struct ipmi_ek_multi_header * prev;
185c18ec02fSPetter Reinholdtsen    struct ipmi_ek_multi_header * next;
186c18ec02fSPetter Reinholdtsen };
187c18ec02fSPetter Reinholdtsen 
188c18ec02fSPetter Reinholdtsen struct ipmi_ek_amc_p2p_connectivity_record{
189c18ec02fSPetter Reinholdtsen    unsigned char guid_count;
190c18ec02fSPetter Reinholdtsen    struct fru_picmgext_guid * oem_guid;
191c18ec02fSPetter Reinholdtsen    unsigned char rsc_id;
192c18ec02fSPetter Reinholdtsen    unsigned char ch_count;
193c18ec02fSPetter Reinholdtsen    struct fru_picmgext_amc_channel_desc_record * ch_desc;
194c18ec02fSPetter Reinholdtsen    unsigned char link_desc_count;
195c18ec02fSPetter Reinholdtsen    struct fru_picmgext_amc_link_desc_record * link_desc;
196c18ec02fSPetter Reinholdtsen    int * matching_result; /*For link descriptor comparision*/
197c18ec02fSPetter Reinholdtsen };
198c18ec02fSPetter Reinholdtsen 
199c18ec02fSPetter Reinholdtsen /*****************************************************************************
200c18ec02fSPetter Reinholdtsen * Function prototype
201c18ec02fSPetter Reinholdtsen ******************************************************************************/
202c18ec02fSPetter Reinholdtsen /****************************************************************************
203c18ec02fSPetter Reinholdtsen * command Functions
204c18ec02fSPetter Reinholdtsen *****************************************************************************/
205c18ec02fSPetter Reinholdtsen static int ipmi_ekanalyzer_print( int argc, char * opt,
206c18ec02fSPetter Reinholdtsen                         char ** filename, int * file_type );
207c18ec02fSPetter Reinholdtsen 
208c18ec02fSPetter Reinholdtsen static tboolean ipmi_ekanalyzer_ekeying_match( int argc, char * opt,
209c18ec02fSPetter Reinholdtsen                         char ** filename, int * file_type );
210c18ec02fSPetter Reinholdtsen 
211c18ec02fSPetter Reinholdtsen /****************************************************************************
212c18ec02fSPetter Reinholdtsen * Linked list Functions
213c18ec02fSPetter Reinholdtsen *****************************************************************************/
214c18ec02fSPetter Reinholdtsen static void ipmi_ek_add_record2list( struct ipmi_ek_multi_header ** record,
215c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header ** list_head,
216c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header ** list_last );
217c18ec02fSPetter Reinholdtsen 
218c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_record( struct ipmi_ek_multi_header * record,
219c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * list_head,
220c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * list_last );
221c18ec02fSPetter Reinholdtsen 
222c18ec02fSPetter Reinholdtsen static void ipmi_ek_remove_record_from_list(
223c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record,
224c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header ** list_head,
225c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header ** list_last );
226c18ec02fSPetter Reinholdtsen 
227c18ec02fSPetter Reinholdtsen static int ipmi_ekanalyzer_fru_file2structure( char * filename,
228c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header ** list_head,
229c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header ** list_record,
230c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header ** list_last );
231c18ec02fSPetter Reinholdtsen 
232c18ec02fSPetter Reinholdtsen /****************************************************************************
233c18ec02fSPetter Reinholdtsen * Ekeying match Functions
234c18ec02fSPetter Reinholdtsen *****************************************************************************/
235c18ec02fSPetter Reinholdtsen static int ipmi_ek_matching_process( int * file_type, int index1, int index2,
236c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header ** list_head,
237c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header ** list_last, char * opt,
238c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * pphysical );
239c18ec02fSPetter Reinholdtsen 
240c18ec02fSPetter Reinholdtsen static int ipmi_ek_get_resource_descriptor( int port_count, int index,
241c18ec02fSPetter Reinholdtsen       struct fru_picmgext_carrier_p2p_descriptor * port_desc,
242c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
243c18ec02fSPetter Reinholdtsen 
244c18ec02fSPetter Reinholdtsen static int ipmi_ek_create_amc_p2p_record( struct ipmi_ek_multi_header * record,
245c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record * amc_record );
246c18ec02fSPetter Reinholdtsen 
247c18ec02fSPetter Reinholdtsen static int ipmi_ek_compare_link( struct ipmi_ek_multi_header * physic_record,
248c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record record1,
249c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record record2,
250c18ec02fSPetter Reinholdtsen       char * opt, int file_type1, int file_type2 );
251c18ec02fSPetter Reinholdtsen 
252c18ec02fSPetter Reinholdtsen static tboolean ipmi_ek_compare_channel_descriptor(
253c18ec02fSPetter Reinholdtsen       struct fru_picmgext_amc_channel_desc_record ch_desc1,
254c18ec02fSPetter Reinholdtsen       struct fru_picmgext_amc_channel_desc_record ch_desc2,
255c18ec02fSPetter Reinholdtsen       struct fru_picmgext_carrier_p2p_descriptor * port_desc,
256c18ec02fSPetter Reinholdtsen       int index_port, unsigned char rsc_id );
257c18ec02fSPetter Reinholdtsen 
258c18ec02fSPetter Reinholdtsen static int ipmi_ek_compare_link_descriptor(
259c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record record1, int index1,
260c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record record2, int index2 );
261c18ec02fSPetter Reinholdtsen 
262c18ec02fSPetter Reinholdtsen static int ipmi_ek_compare_asym( unsigned char asym[COMPARE_CANDIDATE] );
263c18ec02fSPetter Reinholdtsen 
264c18ec02fSPetter Reinholdtsen static int ipmi_ek_compare_number_of_enable_port(
265c18ec02fSPetter Reinholdtsen       struct fru_picmgext_amc_link_desc_record link_desc[COMPARE_CANDIDATE] );
266c18ec02fSPetter Reinholdtsen 
267c18ec02fSPetter Reinholdtsen static int ipmi_ek_check_physical_connectivity(
268c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record record1, int index1,
269c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record record2, int index2,
270c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record,
271c18ec02fSPetter Reinholdtsen       int filetype1, int filetype2, char * option );
272c18ec02fSPetter Reinholdtsen 
273c18ec02fSPetter Reinholdtsen /****************************************************************************
274c18ec02fSPetter Reinholdtsen * Display Functions
275c18ec02fSPetter Reinholdtsen *****************************************************************************/
276c18ec02fSPetter Reinholdtsen static int ipmi_ek_display_fru_header( char * filename );
277c18ec02fSPetter Reinholdtsen 
278c18ec02fSPetter Reinholdtsen static int ipmi_ek_display_fru_header_detail(char * filename);
279c18ec02fSPetter Reinholdtsen 
280c18ec02fSPetter Reinholdtsen static int ipmi_ek_display_chassis_info_area(FILE * input_file, long offset);
281c18ec02fSPetter Reinholdtsen 
282c18ec02fSPetter Reinholdtsen static size_t ipmi_ek_display_board_info_area( FILE * input_file,
283c18ec02fSPetter Reinholdtsen       char * board_type, unsigned int * board_length );
284c18ec02fSPetter Reinholdtsen 
285c18ec02fSPetter Reinholdtsen static int ipmi_ek_display_product_info_area(FILE * input_file, long offset);
286c18ec02fSPetter Reinholdtsen 
287c18ec02fSPetter Reinholdtsen static tboolean ipmi_ek_display_link_descriptor( int file_type,
288c18ec02fSPetter Reinholdtsen       unsigned char rsc_id, char * str,
289c18ec02fSPetter Reinholdtsen       struct fru_picmgext_amc_link_desc_record link_desc );
290c18ec02fSPetter Reinholdtsen 
291c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_oem_guid(
292c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record amc_record1 );
293c18ec02fSPetter Reinholdtsen 
294c18ec02fSPetter Reinholdtsen static int ipmi_ek_display_carrier_connectivity(
295c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
296c18ec02fSPetter Reinholdtsen 
297c18ec02fSPetter Reinholdtsen static int ipmi_ek_display_power( int argc, char * opt,
298c18ec02fSPetter Reinholdtsen       char ** filename, int * file_type );
299c18ec02fSPetter Reinholdtsen 
300c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_current_descriptor(
301c18ec02fSPetter Reinholdtsen       struct fru_picmgext_carrier_activation_record car,
302c18ec02fSPetter Reinholdtsen       struct fru_picmgext_activation_record * cur_desc, char * filename );
303c18ec02fSPetter Reinholdtsen 
304c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_backplane_p2p_record(
305c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
306c18ec02fSPetter Reinholdtsen 
307c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_address_table_record(
308c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
309c18ec02fSPetter Reinholdtsen 
310c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_shelf_power_distribution_record(
311c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
312c18ec02fSPetter Reinholdtsen 
313c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_shelf_activation_record(
314c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
315c18ec02fSPetter Reinholdtsen 
316c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_shelf_ip_connection_record(
317c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
318c18ec02fSPetter Reinholdtsen 
319c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_shelf_fan_geography_record(
320c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
321c18ec02fSPetter Reinholdtsen 
322c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_board_p2p_record(
323c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
324c18ec02fSPetter Reinholdtsen 
325c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_radial_ipmb0_record(
326c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
327c18ec02fSPetter Reinholdtsen 
328c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_amc_current_record(
329c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
330c18ec02fSPetter Reinholdtsen 
331c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_amc_activation_record (
332c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
333c18ec02fSPetter Reinholdtsen 
334c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_amc_p2p_record(
335c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
336c18ec02fSPetter Reinholdtsen 
337c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_amc_carrier_info_record(
338c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
339c18ec02fSPetter Reinholdtsen 
340c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_clock_carrier_p2p_record(
341c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
342c18ec02fSPetter Reinholdtsen 
343c18ec02fSPetter Reinholdtsen static void ipmi_ek_display_clock_config_record(
344c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record );
345c18ec02fSPetter Reinholdtsen 
346c18ec02fSPetter Reinholdtsen /**************************************************************************
347c18ec02fSPetter Reinholdtsen *
348c18ec02fSPetter Reinholdtsen * Function name: ipmi_ekanalyzer_usage
349c18ec02fSPetter Reinholdtsen *
350c18ec02fSPetter Reinholdtsen * Description  : Print the usage (help menu) of ekeying analyzer tool
351c18ec02fSPetter Reinholdtsen *
352c18ec02fSPetter Reinholdtsen * Restriction  : None
353c18ec02fSPetter Reinholdtsen *
354c18ec02fSPetter Reinholdtsen * Input        : None
355c18ec02fSPetter Reinholdtsen *
356c18ec02fSPetter Reinholdtsen * Output       : None
357c18ec02fSPetter Reinholdtsen *
358c18ec02fSPetter Reinholdtsen * Global       : None
359c18ec02fSPetter Reinholdtsen *
360c18ec02fSPetter Reinholdtsen * Return       :   None
361c18ec02fSPetter Reinholdtsen *
362c18ec02fSPetter Reinholdtsen ***************************************************************************/
363c18ec02fSPetter Reinholdtsen static void
ipmi_ekanalyzer_usage(void)364c18ec02fSPetter Reinholdtsen ipmi_ekanalyzer_usage(void)
365c18ec02fSPetter Reinholdtsen {
366b37b9149SZdenek Styblik 	lprintf(LOG_NOTICE,
367b37b9149SZdenek Styblik "Ekeying analyzer tool version 1.00");
368b37b9149SZdenek Styblik 	lprintf(LOG_NOTICE,
369b37b9149SZdenek Styblik "ekanalyzer Commands:");
370c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE,
371c18ec02fSPetter Reinholdtsen "      print    [carrier | power | all] <oc=filename1> <b1=filename2>...");
372c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE,
373c18ec02fSPetter Reinholdtsen "      frushow  <b2=filename>");
374c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE,
375c18ec02fSPetter Reinholdtsen "      summary  [match | unmatch | all] <oc=filename1> <b1=filename2>...");
376c18ec02fSPetter Reinholdtsen }
377c18ec02fSPetter Reinholdtsen 
378c18ec02fSPetter Reinholdtsen /**************************************************************************
379c18ec02fSPetter Reinholdtsen *
380c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_get_file_type
381c18ec02fSPetter Reinholdtsen *
382c18ec02fSPetter Reinholdtsen * Description: this function takes an argument, then xtract the file type and
383c18ec02fSPetter Reinholdtsen *              convert into module type (on carrier, AMC,...) value.
384c18ec02fSPetter Reinholdtsen *
385c18ec02fSPetter Reinholdtsen *
386c18ec02fSPetter Reinholdtsen * Restriction: None
387c18ec02fSPetter Reinholdtsen *
388c18ec02fSPetter Reinholdtsen * Input:       argument: strings contain the type and the name of the file
389c18ec02fSPetter Reinholdtsen *                        together
390c18ec02fSPetter Reinholdtsen *
391c18ec02fSPetter Reinholdtsen * Output:      None
392c18ec02fSPetter Reinholdtsen *
393c18ec02fSPetter Reinholdtsen * Global:      None
394c18ec02fSPetter Reinholdtsen *
395c18ec02fSPetter Reinholdtsen * Return:      Return value of module type: On carrier FRU file, A1 FRUM file...
396c18ec02fSPetter Reinholdtsen *           if the file type is invalid, it return -1. See structure
397c18ec02fSPetter Reinholdtsen *           ipmi_ekanalyzer_module_type for a list of valid type.
398c18ec02fSPetter Reinholdtsen ***************************************************************************/
399c18ec02fSPetter Reinholdtsen static int
ipmi_ek_get_file_type(char * argument)400c18ec02fSPetter Reinholdtsen ipmi_ek_get_file_type(char *argument)
401c18ec02fSPetter Reinholdtsen {
402c18ec02fSPetter Reinholdtsen 	int filetype = ERROR_STATUS;
403b37b9149SZdenek Styblik 	if (strlen(argument) <= MIN_ARGUMENT) {
404b37b9149SZdenek Styblik 		return filetype;
405b37b9149SZdenek Styblik 	}
406c18ec02fSPetter Reinholdtsen 	if (strncmp(argument, "oc=", SIZE_OF_FILE_TYPE) == 0) {
407c18ec02fSPetter Reinholdtsen 		filetype = ON_CARRIER_FRU_FILE;
408b37b9149SZdenek Styblik 	} else if (strncmp(argument, "a1=", SIZE_OF_FILE_TYPE) == 0) {
409c18ec02fSPetter Reinholdtsen 		filetype = A1_AMC_FRU_FILE;
410b37b9149SZdenek Styblik 	} else if (strncmp(argument, "a2=", SIZE_OF_FILE_TYPE) == 0) {
411c18ec02fSPetter Reinholdtsen 		filetype = A2_AMC_FRU_FILE;
412b37b9149SZdenek Styblik 	} else if (strncmp(argument, "a3=", SIZE_OF_FILE_TYPE) == 0) {
413c18ec02fSPetter Reinholdtsen 		filetype = A3_AMC_FRU_FILE;
414b37b9149SZdenek Styblik 	} else if (strncmp(argument, "a4=", SIZE_OF_FILE_TYPE) == 0) {
415c18ec02fSPetter Reinholdtsen 		filetype = A4_AMC_FRU_FILE;
416b37b9149SZdenek Styblik 	} else if (strncmp(argument, "b1=", SIZE_OF_FILE_TYPE) == 0) {
417c18ec02fSPetter Reinholdtsen 		filetype = B1_AMC_FRU_FILE;
418b37b9149SZdenek Styblik 	} else if (strncmp(argument, "b2=", SIZE_OF_FILE_TYPE) == 0) {
419c18ec02fSPetter Reinholdtsen 		filetype = B2_AMC_FRU_FILE;
420b37b9149SZdenek Styblik 	} else if (strncmp(argument, "b3=", SIZE_OF_FILE_TYPE) == 0) {
421c18ec02fSPetter Reinholdtsen 		filetype = B3_AMC_FRU_FILE;
422b37b9149SZdenek Styblik 	} else if (strncmp(argument, "b4=", SIZE_OF_FILE_TYPE) == 0) {
423c18ec02fSPetter Reinholdtsen 		filetype = B4_AMC_FRU_FILE;
424b37b9149SZdenek Styblik 	} else if (strncmp(argument, "rt=", SIZE_OF_FILE_TYPE) == 0) {
425c18ec02fSPetter Reinholdtsen 		filetype = RTM_FRU_FILE;
426b37b9149SZdenek Styblik 	} else if (strncmp(argument, "rc=", SIZE_OF_FILE_TYPE) == 0) {
427c18ec02fSPetter Reinholdtsen 		filetype = CONFIG_FILE;
428b37b9149SZdenek Styblik 	} else if (strncmp(argument, "sm=", SIZE_OF_FILE_TYPE) == 0) {
429c18ec02fSPetter Reinholdtsen 		filetype = SHELF_MANAGER_FRU_FILE;
430b37b9149SZdenek Styblik 	} else {
431c18ec02fSPetter Reinholdtsen 		filetype = ERROR_STATUS;
432c18ec02fSPetter Reinholdtsen 	}
433c18ec02fSPetter Reinholdtsen 	return filetype;
434c18ec02fSPetter Reinholdtsen }
435c18ec02fSPetter Reinholdtsen 
436c18ec02fSPetter Reinholdtsen /**************************************************************************
437c18ec02fSPetter Reinholdtsen *
438c18ec02fSPetter Reinholdtsen * Function name: ipmi_ekanalyzer_main
439c18ec02fSPetter Reinholdtsen *
440c18ec02fSPetter Reinholdtsen * Description: Main program of ekeying analyzer. It calls the appropriate
441c18ec02fSPetter Reinholdtsen *           function according to the command received.
442c18ec02fSPetter Reinholdtsen *
443c18ec02fSPetter Reinholdtsen * Restriction: None
444c18ec02fSPetter Reinholdtsen *
445c18ec02fSPetter Reinholdtsen * Input: ipmi_intf * intf: ?
446c18ec02fSPetter Reinholdtsen *        int argc : number of argument received
447c18ec02fSPetter Reinholdtsen *        int ** argv: argument strings
448c18ec02fSPetter Reinholdtsen *
449c18ec02fSPetter Reinholdtsen * Output: None
450c18ec02fSPetter Reinholdtsen *
451c18ec02fSPetter Reinholdtsen * Global: None
452c18ec02fSPetter Reinholdtsen *
453c18ec02fSPetter Reinholdtsen * Return:   OK_STATUS as succes or ERROR_STATUS as error
454c18ec02fSPetter Reinholdtsen *
455c18ec02fSPetter Reinholdtsen ***************************************************************************/
456c18ec02fSPetter Reinholdtsen int
ipmi_ekanalyzer_main(struct ipmi_intf * intf,int argc,char ** argv)457c18ec02fSPetter Reinholdtsen ipmi_ekanalyzer_main(struct ipmi_intf *intf, int argc, char **argv)
458c18ec02fSPetter Reinholdtsen {
459c18ec02fSPetter Reinholdtsen 	int rc = ERROR_STATUS;
460c18ec02fSPetter Reinholdtsen 	int file_type[MAX_FILE_NUMBER];
461c18ec02fSPetter Reinholdtsen 	int tmp_ret = 0;
462c18ec02fSPetter Reinholdtsen 	char *filename[MAX_FILE_NUMBER];
463c18ec02fSPetter Reinholdtsen 	unsigned int argument_offset = 0;
464c18ec02fSPetter Reinholdtsen 	unsigned int type_offset = 0;
465c18ec02fSPetter Reinholdtsen 	/* list des multi record */
466c18ec02fSPetter Reinholdtsen 	struct ipmi_ek_multi_header *list_head = NULL;
467c18ec02fSPetter Reinholdtsen 	struct ipmi_ek_multi_header *list_record = NULL;
468c18ec02fSPetter Reinholdtsen 	struct ipmi_ek_multi_header *list_last = NULL;
469c18ec02fSPetter Reinholdtsen 
470b37b9149SZdenek Styblik 	if (argc == 0) {
471b37b9149SZdenek Styblik 		lprintf(LOG_ERR, "Not enough parameters given.");
472c18ec02fSPetter Reinholdtsen 		ipmi_ekanalyzer_usage();
473b37b9149SZdenek Styblik 		return (-1);
474b37b9149SZdenek Styblik 	} else if ((argc - 1) > MAX_FILE_NUMBER) {
475b37b9149SZdenek Styblik 		lprintf(LOG_ERR, "Too too many parameters given.");
476b37b9149SZdenek Styblik 		return (-1);
477c18ec02fSPetter Reinholdtsen 	}
478b37b9149SZdenek Styblik 
479b37b9149SZdenek Styblik 	if (strcmp(argv[argument_offset], "help") == 0) {
480c18ec02fSPetter Reinholdtsen 		ipmi_ekanalyzer_usage();
481b37b9149SZdenek Styblik 		return 0;
482b37b9149SZdenek Styblik 	} else if ((strcmp(argv[argument_offset], "frushow") == 0)
483b37b9149SZdenek Styblik 			&& (argc > (MIN_ARGUMENT-1))) {
484c18ec02fSPetter Reinholdtsen 		for (type_offset = 0; type_offset < (argc-1); type_offset++ ) {
485c18ec02fSPetter Reinholdtsen 			argument_offset++;
486c18ec02fSPetter Reinholdtsen 			file_type[type_offset] = ipmi_ek_get_file_type(argv[argument_offset]);
487b37b9149SZdenek Styblik 			if (file_type[type_offset] == ERROR_STATUS
488b37b9149SZdenek Styblik 					|| file_type[type_offset] == CONFIG_FILE) {
489b37b9149SZdenek Styblik 				lprintf(LOG_ERR, "Invalid file type!");
490b37b9149SZdenek Styblik 				lprintf(LOG_ERR, "   ekanalyzer frushow <xx=frufile> ...");
491b37b9149SZdenek Styblik 				return (-1);
492b37b9149SZdenek Styblik 			}
493b37b9149SZdenek Styblik 			/* because of strlen doesn't count '\0',
494b37b9149SZdenek Styblik 			 * we need to add 1 byte for this character
495b37b9149SZdenek Styblik 			 * to filename size
496c18ec02fSPetter Reinholdtsen 			 */
497b37b9149SZdenek Styblik 			filename[type_offset] = malloc(strlen(argv[argument_offset])
498b37b9149SZdenek Styblik 					+ 1 - SIZE_OF_FILE_TYPE);
499b37b9149SZdenek Styblik 			if (filename[type_offset] == NULL) {
500b37b9149SZdenek Styblik 				lprintf(LOG_ERR, "malloc failure");
501b37b9149SZdenek Styblik 				return (-1);
502b37b9149SZdenek Styblik 			}
503c18ec02fSPetter Reinholdtsen 			strcpy(filename[type_offset],
504c18ec02fSPetter Reinholdtsen 					&argv[argument_offset][SIZE_OF_FILE_TYPE]);
505b37b9149SZdenek Styblik 			printf("Start converting file '%s'...\n",
506b37b9149SZdenek Styblik 					filename[type_offset]);
507c18ec02fSPetter Reinholdtsen 			/* Display FRU header offset */
508c18ec02fSPetter Reinholdtsen 			rc = ipmi_ek_display_fru_header (filename[type_offset]);
509c18ec02fSPetter Reinholdtsen 			if (rc != ERROR_STATUS) {
510c18ec02fSPetter Reinholdtsen 				/* Display FRU header info in detail record */
511c18ec02fSPetter Reinholdtsen 				tmp_ret = ipmi_ek_display_fru_header_detail(filename[type_offset]);
512c18ec02fSPetter Reinholdtsen 				/* Convert from binary data into multi record structure */
513c18ec02fSPetter Reinholdtsen 				rc = ipmi_ekanalyzer_fru_file2structure (filename[type_offset],
514c18ec02fSPetter Reinholdtsen 						&list_head, &list_record, &list_last );
515c18ec02fSPetter Reinholdtsen 				ipmi_ek_display_record(list_record, list_head, list_last);
516c18ec02fSPetter Reinholdtsen 				/* Remove record of list */
517c18ec02fSPetter Reinholdtsen 				while (list_head != NULL) {
518c18ec02fSPetter Reinholdtsen 					ipmi_ek_remove_record_from_list(list_head,
519c18ec02fSPetter Reinholdtsen 							&list_head,&list_last );
520b37b9149SZdenek Styblik 					if (verbose > 1) {
521c18ec02fSPetter Reinholdtsen 						printf("record has been removed!\n");
522c18ec02fSPetter Reinholdtsen 					}
523c18ec02fSPetter Reinholdtsen 				}
524b37b9149SZdenek Styblik 			}
525c18ec02fSPetter Reinholdtsen 			free(filename[type_offset]);
526c18ec02fSPetter Reinholdtsen 			filename[type_offset] = NULL;
527c18ec02fSPetter Reinholdtsen 		}
528b37b9149SZdenek Styblik 	} else if ((strcmp(argv[argument_offset], "print") == 0)
529b37b9149SZdenek Styblik 			|| (strcmp(argv[argument_offset], "summary") == 0)) {
530b37b9149SZdenek Styblik 		/* Display help text for corresponding command
531b37b9149SZdenek Styblik 		 * if not enough parameters were given.
532c18ec02fSPetter Reinholdtsen 		 */
533b37b9149SZdenek Styblik 		char * option;
534b37b9149SZdenek Styblik 		/* index=1 indicates start position of first file
535b37b9149SZdenek Styblik 		 * name in command line
536b37b9149SZdenek Styblik 		 */
537b37b9149SZdenek Styblik 		int index = 1;
538b37b9149SZdenek Styblik 		int filename_size=0;
539c18ec02fSPetter Reinholdtsen 		if (argc < MIN_ARGUMENT) {
540c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Not enough parameters given.");
541c18ec02fSPetter Reinholdtsen 			if (strcmp(argv[argument_offset], "print") == 0) {
542b37b9149SZdenek Styblik 				lprintf(LOG_ERR,
543b37b9149SZdenek Styblik 						"   ekanalyzer print [carrier/power/all]"
544b37b9149SZdenek Styblik 						" <xx=frufile> <xx=frufile> [xx=frufile]");
545b37b9149SZdenek Styblik 			} else {
546b37b9149SZdenek Styblik 				lprintf(LOG_ERR,
547b37b9149SZdenek Styblik 						"   ekanalyzer summary [match/ unmatch/ all]"
548b37b9149SZdenek Styblik 						" <xx=frufile> <xx=frufile> [xx=frufile]");
549c18ec02fSPetter Reinholdtsen 			}
550b37b9149SZdenek Styblik 			return ERROR_STATUS;
551c18ec02fSPetter Reinholdtsen 		}
552c18ec02fSPetter Reinholdtsen 		argument_offset++;
553c18ec02fSPetter Reinholdtsen 		if ((strcmp(argv[argument_offset], "carrier") == 0)
554c18ec02fSPetter Reinholdtsen 				|| (strcmp(argv[argument_offset], "power") == 0)
555b37b9149SZdenek Styblik 				|| (strcmp(argv[argument_offset], "all") == 0)) {
556c18ec02fSPetter Reinholdtsen 			option = argv[argument_offset];
557c18ec02fSPetter Reinholdtsen 			index ++;
558c18ec02fSPetter Reinholdtsen 			argc--;
559b37b9149SZdenek Styblik 		} else if ((strcmp(argv[argument_offset], "match") == 0)
560b37b9149SZdenek Styblik 				|| ( strcmp(argv[argument_offset], "unmatch") == 0)) {
561c18ec02fSPetter Reinholdtsen 			option = argv[argument_offset];
562c18ec02fSPetter Reinholdtsen 			index ++;
563c18ec02fSPetter Reinholdtsen 			argc--;
564b37b9149SZdenek Styblik 		} else if ( strncmp(&argv[argument_offset][2], "=", 1) == 0) {
565b37b9149SZdenek Styblik 			/* since the command line must receive xx=filename,
566b37b9149SZdenek Styblik 			 * so the position of "=" sign is 2
567c18ec02fSPetter Reinholdtsen 			 */
568c18ec02fSPetter Reinholdtsen 			option = "default";
569c18ec02fSPetter Reinholdtsen 			/* Since there is no option from user, the first argument
570b37b9149SZdenek Styblik 			 * becomes first file type
571b37b9149SZdenek Styblik 			 */
572c18ec02fSPetter Reinholdtsen 			index = 1; /* index of argument */
573b37b9149SZdenek Styblik 		} else {
574c18ec02fSPetter Reinholdtsen 			option = "invalid";
575c18ec02fSPetter Reinholdtsen 			printf("Invalid option '%s'\n", argv[argument_offset]);
576c18ec02fSPetter Reinholdtsen 			argument_offset--;
577c18ec02fSPetter Reinholdtsen 			if (strcmp(argv[0], "print") == 0) {
578b37b9149SZdenek Styblik 				lprintf (LOG_ERR,
579b37b9149SZdenek Styblik 						"   ekanalyzer print [carrier/power/all]"
580b37b9149SZdenek Styblik 						" <xx=frufile> <xx=frufile> [xx=frufile]");
581b37b9149SZdenek Styblik 			} else {
582b37b9149SZdenek Styblik 				lprintf (LOG_ERR,
583b37b9149SZdenek Styblik 						"   ekanalyzer summary [match/ unmatch/ all]"
584b37b9149SZdenek Styblik 						" <xx=frufile> <xx=frufile> [xx=frufile]");
585c18ec02fSPetter Reinholdtsen 			}
586c18ec02fSPetter Reinholdtsen 			rc = ERROR_STATUS;
587c18ec02fSPetter Reinholdtsen 		}
588c18ec02fSPetter Reinholdtsen 		if (strcmp(option, "invalid") != 0) {
589c18ec02fSPetter Reinholdtsen 			int i=0;
590c18ec02fSPetter Reinholdtsen 			for (i = 0; i < (argc-1); i++) {
591c18ec02fSPetter Reinholdtsen 				file_type[i] = ipmi_ek_get_file_type (argv[index]);
592c18ec02fSPetter Reinholdtsen 				if (file_type[i] == ERROR_STATUS) {
593c18ec02fSPetter Reinholdtsen 					/* display the first 2 charactors (file type) of argument */
594b37b9149SZdenek Styblik 					lprintf(LOG_ERR, "Invalid file type: %c%c\n",
595b37b9149SZdenek Styblik 							argv[index][0],
596c18ec02fSPetter Reinholdtsen 							argv[index][1]);
597c18ec02fSPetter Reinholdtsen 					ipmi_ekanalyzer_usage();
598c18ec02fSPetter Reinholdtsen 					rc = ERROR_STATUS;
599c18ec02fSPetter Reinholdtsen 					break;
600c18ec02fSPetter Reinholdtsen 				}
601c18ec02fSPetter Reinholdtsen 				/* size is equal to string size minus 3 bytes of file type plus
602c18ec02fSPetter Reinholdtsen 				 * 1 byte of '\0' since the strlen doesn't count the '\0'
603c18ec02fSPetter Reinholdtsen 				 */
604c18ec02fSPetter Reinholdtsen 				filename_size = strlen(argv[index]) - SIZE_OF_FILE_TYPE + 1;
605c18ec02fSPetter Reinholdtsen 				if (filename_size > 0) {
606b37b9149SZdenek Styblik 					/* TODO - check malloc() retval */
607c18ec02fSPetter Reinholdtsen 					filename[i] = malloc( filename_size );
608b37b9149SZdenek Styblik 					if (filename[i] != NULL) {
609c18ec02fSPetter Reinholdtsen 						strcpy(filename[i], &argv[index][SIZE_OF_FILE_TYPE]);
610c18ec02fSPetter Reinholdtsen 					}
611b37b9149SZdenek Styblik 				}
612c18ec02fSPetter Reinholdtsen 				rc = OK_STATUS;
613c18ec02fSPetter Reinholdtsen 				index++;
614c18ec02fSPetter Reinholdtsen 			}
615c18ec02fSPetter Reinholdtsen 			if (rc != ERROR_STATUS) {
616c18ec02fSPetter Reinholdtsen 				if (verbose > 0) {
617c18ec02fSPetter Reinholdtsen 					for (i = 0; i < (argc-1); i++) {
618c18ec02fSPetter Reinholdtsen 						printf ("Type: %s,   ",
619b37b9149SZdenek Styblik 								val2str(file_type[i],
620b37b9149SZdenek Styblik 									ipmi_ekanalyzer_module_type));
621c18ec02fSPetter Reinholdtsen 						printf("file name: %s\n", filename[i]);
622c18ec02fSPetter Reinholdtsen 					}
623c18ec02fSPetter Reinholdtsen 				}
624c18ec02fSPetter Reinholdtsen 				if (strcmp(argv[0], "print") == 0) {
625b37b9149SZdenek Styblik 					rc = ipmi_ekanalyzer_print((argc-1),
626b37b9149SZdenek Styblik 							option, filename, file_type);
627b37b9149SZdenek Styblik 				} else {
628b37b9149SZdenek Styblik 					rc = ipmi_ekanalyzer_ekeying_match((argc-1),
629b37b9149SZdenek Styblik 							option, filename, file_type);
630c18ec02fSPetter Reinholdtsen 				}
631c18ec02fSPetter Reinholdtsen 				for (i = 0; i < (argc-1); i++) {
632c18ec02fSPetter Reinholdtsen 					if (filename[i] != NULL) {
633c18ec02fSPetter Reinholdtsen 						free(filename[i]);
634c18ec02fSPetter Reinholdtsen 						filename[i] = NULL;
635c18ec02fSPetter Reinholdtsen 					}
636c18ec02fSPetter Reinholdtsen 				}
637c18ec02fSPetter Reinholdtsen 			} /* End of ERROR_STATUS */
638c18ec02fSPetter Reinholdtsen 		} /* End of comparison of invalid option */
639b37b9149SZdenek Styblik 	} else {
640c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid ekanalyzer command: %s", argv[0]);
641c18ec02fSPetter Reinholdtsen 		ipmi_ekanalyzer_usage();
642c18ec02fSPetter Reinholdtsen 		rc = ERROR_STATUS;
643c18ec02fSPetter Reinholdtsen 	}
644c18ec02fSPetter Reinholdtsen 	return rc;
645c18ec02fSPetter Reinholdtsen }
646c18ec02fSPetter Reinholdtsen 
647c18ec02fSPetter Reinholdtsen /**************************************************************************
648c18ec02fSPetter Reinholdtsen *
649c18ec02fSPetter Reinholdtsen * Function name: ipmi_ekanalyzer_print
650c18ec02fSPetter Reinholdtsen *
651c18ec02fSPetter Reinholdtsen * Description: this function will display the topology, power or both
652c18ec02fSPetter Reinholdtsen *            information together according to the option that it received.
653c18ec02fSPetter Reinholdtsen *
654c18ec02fSPetter Reinholdtsen * Restriction: None
655c18ec02fSPetter Reinholdtsen *
656c18ec02fSPetter Reinholdtsen * Input: int argc: number of the argument received
657c18ec02fSPetter Reinholdtsen *       char* opt: option string that will tell what to display
658c18ec02fSPetter Reinholdtsen *       char** filename: strings that contained filename of FRU data binary file
659c18ec02fSPetter Reinholdtsen *       int* file_type: a pointer that contain file type (on carrier file,
660c18ec02fSPetter Reinholdtsen *                       a1 file, b1 file...). See structure
661c18ec02fSPetter Reinholdtsen *                       ipmi_ekanalyzer_module_type for a list of valid type
662c18ec02fSPetter Reinholdtsen *
663c18ec02fSPetter Reinholdtsen * Output: None
664c18ec02fSPetter Reinholdtsen *
665c18ec02fSPetter Reinholdtsen * Global: None
666c18ec02fSPetter Reinholdtsen *
667c18ec02fSPetter Reinholdtsen * Return:   return 0 as success and -1 as error.
668c18ec02fSPetter Reinholdtsen *
669c18ec02fSPetter Reinholdtsen ***************************************************************************/
670c18ec02fSPetter Reinholdtsen static int
ipmi_ekanalyzer_print(int argc,char * opt,char ** filename,int * file_type)671c18ec02fSPetter Reinholdtsen ipmi_ekanalyzer_print(int argc, char *opt, char **filename, int *file_type)
672c18ec02fSPetter Reinholdtsen {
673c18ec02fSPetter Reinholdtsen 	int return_value = OK_STATUS;
674c18ec02fSPetter Reinholdtsen 	/* Display carrier topology */
675c18ec02fSPetter Reinholdtsen 	if ((strcmp(opt, "carrier") == 0) || (strcmp(opt, "default") == 0)) {
676c18ec02fSPetter Reinholdtsen 		tboolean found_flag = FALSE;
677c18ec02fSPetter Reinholdtsen 		int index = 0;
678c18ec02fSPetter Reinholdtsen 		int index_name[argc];
679c18ec02fSPetter Reinholdtsen 		int list = 0;
680c18ec02fSPetter Reinholdtsen 		/* list of multi record */
681c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header *list_head[argc];
682c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header *list_record[argc];
683c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header *list_last[argc];
684c18ec02fSPetter Reinholdtsen 
685c18ec02fSPetter Reinholdtsen 		for (list=0; list < argc; list++) {
686c18ec02fSPetter Reinholdtsen 			list_head[list] = NULL;
687c18ec02fSPetter Reinholdtsen 			list_record[list] = NULL;
688c18ec02fSPetter Reinholdtsen 			list_last[list] = NULL;
689c18ec02fSPetter Reinholdtsen 		}
690b37b9149SZdenek Styblik 		/* reset list count */
691b37b9149SZdenek Styblik 		list = 0;
692c18ec02fSPetter Reinholdtsen 		for (index = 0; index < argc; index++) {
693b37b9149SZdenek Styblik 			if (file_type[index] != ON_CARRIER_FRU_FILE) {
694b37b9149SZdenek Styblik 				continue;
695b37b9149SZdenek Styblik 			}
696c18ec02fSPetter Reinholdtsen 			index_name[list] = index;
697c18ec02fSPetter Reinholdtsen 			return_value = ipmi_ekanalyzer_fru_file2structure(filename[index],
698b37b9149SZdenek Styblik 					&list_head[list],
699b37b9149SZdenek Styblik 					&list_record[list],
700b37b9149SZdenek Styblik 					&list_last[list]);
701c18ec02fSPetter Reinholdtsen 			list++;
702c18ec02fSPetter Reinholdtsen 			found_flag = TRUE;
703c18ec02fSPetter Reinholdtsen 		}
704c18ec02fSPetter Reinholdtsen 		if (!found_flag) {
705c18ec02fSPetter Reinholdtsen 			printf("No carrier file has been found\n");
706c18ec02fSPetter Reinholdtsen 			return_value = ERROR_STATUS;
707b37b9149SZdenek Styblik 		} else {
708c18ec02fSPetter Reinholdtsen 			int i = 0;
709c18ec02fSPetter Reinholdtsen 			for (i = 0; i < argc; i++) {
710b37b9149SZdenek Styblik 				/* this is a flag to advoid displaying
711b37b9149SZdenek Styblik 				 * the same data multiple time
712b37b9149SZdenek Styblik 				 */
713c18ec02fSPetter Reinholdtsen 				tboolean first_data = TRUE;
714c18ec02fSPetter Reinholdtsen 				for (list_record[i] = list_head[i];
715c18ec02fSPetter Reinholdtsen 						list_record[i] != NULL;
716c18ec02fSPetter Reinholdtsen 						list_record[i] = list_record[i]->next) {
717b37b9149SZdenek Styblik 					if (list_record[i]->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_P2P) {
718c18ec02fSPetter Reinholdtsen 						if (first_data) {
719c18ec02fSPetter Reinholdtsen 							printf("%s\n", STAR_LINE_LIMITER);
720c18ec02fSPetter Reinholdtsen 							printf("From Carrier file: %s\n", filename[index_name[i]]);
721c18ec02fSPetter Reinholdtsen 							first_data = FALSE;
722c18ec02fSPetter Reinholdtsen 						}
723b37b9149SZdenek Styblik 						return_value = ipmi_ek_display_carrier_connectivity(list_record[i]);
724b37b9149SZdenek Styblik 					} else if (list_record[i]->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_INFO) {
725c18ec02fSPetter Reinholdtsen 						/*See AMC.0 specification Table3-3 for mor detail*/
726c18ec02fSPetter Reinholdtsen 						#define COUNT_OFFSET 6
727c18ec02fSPetter Reinholdtsen 						if (first_data) {
728c18ec02fSPetter Reinholdtsen 							printf("From Carrier file: %s\n", filename[index_name[i]]);
729c18ec02fSPetter Reinholdtsen 							first_data = FALSE;
730c18ec02fSPetter Reinholdtsen 						}
731c18ec02fSPetter Reinholdtsen 						printf("   Number of AMC bays supported by Carrier: %d\n",
732c18ec02fSPetter Reinholdtsen 								list_record[i]->data[COUNT_OFFSET]);
733c18ec02fSPetter Reinholdtsen 					}
734c18ec02fSPetter Reinholdtsen 				}
735c18ec02fSPetter Reinholdtsen 			}
736c18ec02fSPetter Reinholdtsen 			/*Destroy the list of record*/
737c18ec02fSPetter Reinholdtsen 			for (i = 0; i < argc; i++) {
738c18ec02fSPetter Reinholdtsen 				while (list_head[i] != NULL) {
739c18ec02fSPetter Reinholdtsen 					ipmi_ek_remove_record_from_list(list_head[i],
740c18ec02fSPetter Reinholdtsen 							&list_head[i], &list_last[i]);
741c18ec02fSPetter Reinholdtsen 				}
742b37b9149SZdenek Styblik 				/* display deleted result when we
743b37b9149SZdenek Styblik 				 * reach the last record
744b37b9149SZdenek Styblik 				 */
745b37b9149SZdenek Styblik 				if ((i == (list-1)) && verbose) {
746c18ec02fSPetter Reinholdtsen 					printf("Record list has been removed successfully\n");
747c18ec02fSPetter Reinholdtsen 				}
748c18ec02fSPetter Reinholdtsen 			}
749c18ec02fSPetter Reinholdtsen 		}
750b37b9149SZdenek Styblik 	} else if (strcmp(opt, "power") == 0) {
751c18ec02fSPetter Reinholdtsen 		printf("Print power information\n");
752c18ec02fSPetter Reinholdtsen 		return_value = ipmi_ek_display_power(argc, opt, filename, file_type);
753b37b9149SZdenek Styblik 	} else if (strcmp(opt, "all") == 0) {
754c18ec02fSPetter Reinholdtsen 		printf("Print all information\n");
755c18ec02fSPetter Reinholdtsen 		return_value = ipmi_ek_display_power(argc, opt, filename, file_type);
756b37b9149SZdenek Styblik 	} else {
757c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid option %s", opt);
758c18ec02fSPetter Reinholdtsen 		return_value = ERROR_STATUS;
759c18ec02fSPetter Reinholdtsen 	}
760c18ec02fSPetter Reinholdtsen 	return return_value;
761c18ec02fSPetter Reinholdtsen }
762c18ec02fSPetter Reinholdtsen 
763c18ec02fSPetter Reinholdtsen /**************************************************************************
764c18ec02fSPetter Reinholdtsen *
765c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_carrier_connectivity
766c18ec02fSPetter Reinholdtsen *
767c18ec02fSPetter Reinholdtsen * Description: Display the topology between a Carrier and all AMC modules by
768c18ec02fSPetter Reinholdtsen *           using carrier p2p connectivity record
769c18ec02fSPetter Reinholdtsen *
770c18ec02fSPetter Reinholdtsen * Restriction: Ref: AMC.0 Specification: Table 3-13 and Table 3-14
771c18ec02fSPetter Reinholdtsen *
772c18ec02fSPetter Reinholdtsen * Input: struct ipmi_ek_multi_header* record: a pointer to the carrier p2p
773c18ec02fSPetter Reinholdtsen *                              connectivity record.
774c18ec02fSPetter Reinholdtsen *
775c18ec02fSPetter Reinholdtsen * Output: None
776c18ec02fSPetter Reinholdtsen *
777c18ec02fSPetter Reinholdtsen * Global: None
778c18ec02fSPetter Reinholdtsen *
779c18ec02fSPetter Reinholdtsen * Return:   return 0 on success and -1 if the record doesn't exist.
780c18ec02fSPetter Reinholdtsen *
781c18ec02fSPetter Reinholdtsen ***************************************************************************/
782c18ec02fSPetter Reinholdtsen static int
ipmi_ek_display_carrier_connectivity(struct ipmi_ek_multi_header * record)783c18ec02fSPetter Reinholdtsen ipmi_ek_display_carrier_connectivity(struct ipmi_ek_multi_header *record)
784c18ec02fSPetter Reinholdtsen {
785b37b9149SZdenek Styblik 	int offset = START_DATA_OFFSET;
786c18ec02fSPetter Reinholdtsen 	struct fru_picmgext_carrier_p2p_record rsc_desc;
787c18ec02fSPetter Reinholdtsen 	struct fru_picmgext_carrier_p2p_descriptor *port_desc;
788c18ec02fSPetter Reinholdtsen 	if (record == NULL) {
789c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "P2P connectivity record is invalid\n");
790b37b9149SZdenek Styblik 		return ERROR_STATUS;
791c18ec02fSPetter Reinholdtsen 	}
792c18ec02fSPetter Reinholdtsen 	if (verbose > 1) {
793c18ec02fSPetter Reinholdtsen 		int k = 0;
794c18ec02fSPetter Reinholdtsen 		printf("Binary data of Carrier p2p connectivity"\
795c18ec02fSPetter Reinholdtsen 				" record starting from mfg id\n");
796c18ec02fSPetter Reinholdtsen 		for (k = 0; k < (record->header.len); k++) {
797c18ec02fSPetter Reinholdtsen 			printf("%02x   ", record->data[k]);
798c18ec02fSPetter Reinholdtsen 		}
799c18ec02fSPetter Reinholdtsen 		printf("\n");
800c18ec02fSPetter Reinholdtsen 	}
801c18ec02fSPetter Reinholdtsen 	while (offset <= (record->header.len - START_DATA_OFFSET)) {
802c18ec02fSPetter Reinholdtsen 		rsc_desc.resource_id = record->data[offset++];
803c18ec02fSPetter Reinholdtsen 		rsc_desc.p2p_count = record->data[offset++];
804c18ec02fSPetter Reinholdtsen 		if (verbose > 0) {
805c18ec02fSPetter Reinholdtsen 			printf("resource id= %02x  port count= %d\n",
806c18ec02fSPetter Reinholdtsen 					rsc_desc.resource_id, rsc_desc.p2p_count);
807c18ec02fSPetter Reinholdtsen 		}
808c18ec02fSPetter Reinholdtsen 		/* check if it is an AMC Module */
809b37b9149SZdenek Styblik 		if ((rsc_desc.resource_id & AMC_MODULE) == AMC_MODULE) {
810c18ec02fSPetter Reinholdtsen 			/* check if it is an RTM module */
811b37b9149SZdenek Styblik 			if (rsc_desc.resource_id == AMC_MODULE) {
812b37b9149SZdenek Styblik 				printf("   %s topology:\n",
813b37b9149SZdenek Styblik 						val2str(RTM_IPMB_L,
814c18ec02fSPetter Reinholdtsen 							ipmi_ekanalyzer_IPMBL_addr));
815b37b9149SZdenek Styblik 			} else {
816b37b9149SZdenek Styblik 				/* The last four bits of resource ID
817b37b9149SZdenek Styblik 				 * represent site number (mask = 0x0f)
818c18ec02fSPetter Reinholdtsen 				 */
819c18ec02fSPetter Reinholdtsen 				printf("   %s topology:\n",
820c18ec02fSPetter Reinholdtsen 						val2str((rsc_desc.resource_id & 0x0f),
821c18ec02fSPetter Reinholdtsen 							ipmi_ekanalyzer_module_type));
822c18ec02fSPetter Reinholdtsen 			}
823b37b9149SZdenek Styblik 		} else {
824c18ec02fSPetter Reinholdtsen 			printf("   On Carrier Device ID %d topology: \n",
825c18ec02fSPetter Reinholdtsen 					(rsc_desc.resource_id & 0x0f));
826c18ec02fSPetter Reinholdtsen 		}
827c18ec02fSPetter Reinholdtsen 		while (rsc_desc.p2p_count > 0) {
828c18ec02fSPetter Reinholdtsen 			unsigned char data[3];
829c18ec02fSPetter Reinholdtsen # ifndef WORDS_BIGENDIAN
830c18ec02fSPetter Reinholdtsen 			data[0] = record->data[offset + 0];
831c18ec02fSPetter Reinholdtsen 			data[1] = record->data[offset + 1];
832c18ec02fSPetter Reinholdtsen 			data[2] = record->data[offset + 2];
833c18ec02fSPetter Reinholdtsen # else
834c18ec02fSPetter Reinholdtsen 			data[0] = record->data[offset + 2];
835c18ec02fSPetter Reinholdtsen 			data[1] = record->data[offset + 1];
836c18ec02fSPetter Reinholdtsen 			data[2] = record->data[offset + 0];
837c18ec02fSPetter Reinholdtsen # endif
838c18ec02fSPetter Reinholdtsen 			port_desc = (struct fru_picmgext_carrier_p2p_descriptor*)data;
839c18ec02fSPetter Reinholdtsen 			offset += sizeof(struct fru_picmgext_carrier_p2p_descriptor);
840c18ec02fSPetter Reinholdtsen 			if ((port_desc->remote_resource_id & AMC_MODULE) == AMC_MODULE) {
841c18ec02fSPetter Reinholdtsen 				printf("\tPort %d =====> %s, Port %d\n",
842c18ec02fSPetter Reinholdtsen 						port_desc->local_port,
843c18ec02fSPetter Reinholdtsen 						val2str((port_desc->remote_resource_id & 0x0f),
844c18ec02fSPetter Reinholdtsen 							ipmi_ekanalyzer_module_type),
845c18ec02fSPetter Reinholdtsen 						port_desc->remote_port);
846b37b9149SZdenek Styblik 			} else {
847c18ec02fSPetter Reinholdtsen 				printf("\tPort %d =====> On Carrier Device ID %d, Port %d\n",
848c18ec02fSPetter Reinholdtsen 						port_desc->local_port,
849c18ec02fSPetter Reinholdtsen 						(port_desc->remote_resource_id & 0x0f),
850c18ec02fSPetter Reinholdtsen 						port_desc->remote_port);
851c18ec02fSPetter Reinholdtsen 			}
852c18ec02fSPetter Reinholdtsen 			rsc_desc.p2p_count--;
853c18ec02fSPetter Reinholdtsen 		}
854c18ec02fSPetter Reinholdtsen 	}
855b37b9149SZdenek Styblik 	return OK_STATUS;
856c18ec02fSPetter Reinholdtsen }
857c18ec02fSPetter Reinholdtsen 
858c18ec02fSPetter Reinholdtsen /**************************************************************************
859c18ec02fSPetter Reinholdtsen *
860c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_power
861c18ec02fSPetter Reinholdtsen *
862c18ec02fSPetter Reinholdtsen * Description: Display the power management of the Carrier and AMC module by
863c18ec02fSPetter Reinholdtsen *           using current management record. If the display option equal to all,
864c18ec02fSPetter Reinholdtsen *           it will display power and carrier topology together.
865c18ec02fSPetter Reinholdtsen *
866c18ec02fSPetter Reinholdtsen * Restriction: Reference: AMC.0 Specification, Table 3-11
867c18ec02fSPetter Reinholdtsen *
868c18ec02fSPetter Reinholdtsen * Input: int argc: number of the argument received
869c18ec02fSPetter Reinholdtsen *       char* opt: option string that will tell what to display
870c18ec02fSPetter Reinholdtsen *       char** filename: strings that contained filename of FRU data binary file
871c18ec02fSPetter Reinholdtsen *       int* file_type: a pointer that contain file type (on carrier file,
872c18ec02fSPetter Reinholdtsen *                       a1 file, b1 file...)
873c18ec02fSPetter Reinholdtsen *
874c18ec02fSPetter Reinholdtsen * Output: None
875c18ec02fSPetter Reinholdtsen *
876c18ec02fSPetter Reinholdtsen * Global: None
877c18ec02fSPetter Reinholdtsen *
878c18ec02fSPetter Reinholdtsen * Return:   return 0 on success and -1 if the record doesn't exist.
879c18ec02fSPetter Reinholdtsen *
880c18ec02fSPetter Reinholdtsen ***************************************************************************/
881c18ec02fSPetter Reinholdtsen static int
ipmi_ek_display_power(int argc,char * opt,char ** filename,int * file_type)882c18ec02fSPetter Reinholdtsen ipmi_ek_display_power( int argc, char * opt, char ** filename, int * file_type )
883c18ec02fSPetter Reinholdtsen {
884c18ec02fSPetter Reinholdtsen    int num_file=0;
885c18ec02fSPetter Reinholdtsen    int return_value = ERROR_STATUS;
886c18ec02fSPetter Reinholdtsen    int index = 0;
887c18ec02fSPetter Reinholdtsen 
888c18ec02fSPetter Reinholdtsen    /*list des multi record*/
889c18ec02fSPetter Reinholdtsen    struct ipmi_ek_multi_header * list_head[argc];
890c18ec02fSPetter Reinholdtsen    struct ipmi_ek_multi_header * list_record[argc];
891c18ec02fSPetter Reinholdtsen    struct ipmi_ek_multi_header * list_last[argc];
892c18ec02fSPetter Reinholdtsen 
893c18ec02fSPetter Reinholdtsen    for ( num_file = 0; num_file < argc; num_file++ ){
894c18ec02fSPetter Reinholdtsen       list_head[num_file] = NULL;
895c18ec02fSPetter Reinholdtsen       list_record[num_file] = NULL;
896c18ec02fSPetter Reinholdtsen       list_last[num_file] = NULL;
897c18ec02fSPetter Reinholdtsen    }
898c18ec02fSPetter Reinholdtsen 
899c18ec02fSPetter Reinholdtsen    for ( num_file = 0; num_file < argc; num_file++ ){
900c18ec02fSPetter Reinholdtsen       tboolean is_first_data = TRUE;
901c18ec02fSPetter Reinholdtsen       if ( file_type[num_file] == CONFIG_FILE ){
902c18ec02fSPetter Reinholdtsen          num_file++;
903c18ec02fSPetter Reinholdtsen       }
904c18ec02fSPetter Reinholdtsen 
905c18ec02fSPetter Reinholdtsen       if ( is_first_data ){
906c18ec02fSPetter Reinholdtsen          printf("%s\n", STAR_LINE_LIMITER);
907c18ec02fSPetter Reinholdtsen          printf("\nFrom %s file '%s'\n",
908c18ec02fSPetter Reinholdtsen                   val2str( file_type[num_file], ipmi_ekanalyzer_module_type),
909c18ec02fSPetter Reinholdtsen                   filename[num_file]);
910c18ec02fSPetter Reinholdtsen          is_first_data = FALSE;
911c18ec02fSPetter Reinholdtsen       }
912c18ec02fSPetter Reinholdtsen 
913c18ec02fSPetter Reinholdtsen       return_value = ipmi_ekanalyzer_fru_file2structure( filename[num_file],
914c18ec02fSPetter Reinholdtsen         &list_head[num_file], &list_record[num_file], &list_last[num_file]);
915c18ec02fSPetter Reinholdtsen 
916c18ec02fSPetter Reinholdtsen       if ( list_head[num_file] != NULL ){
917c18ec02fSPetter Reinholdtsen          for (    list_record[num_file] = list_head[num_file];
918c18ec02fSPetter Reinholdtsen                   list_record[num_file] != NULL;
919c18ec02fSPetter Reinholdtsen                   list_record[num_file] = list_record[num_file]->next
920c18ec02fSPetter Reinholdtsen             ){
921c18ec02fSPetter Reinholdtsen             if ( ( strcmp(opt, "all") == 0 )
922c18ec02fSPetter Reinholdtsen                   && ( file_type[num_file] == ON_CARRIER_FRU_FILE )
923c18ec02fSPetter Reinholdtsen                ){
924c18ec02fSPetter Reinholdtsen                   if ( list_record[num_file]->data[PICMG_ID_OFFSET]
925c18ec02fSPetter Reinholdtsen                            ==
926c18ec02fSPetter Reinholdtsen                         FRU_AMC_CARRIER_P2P
927c18ec02fSPetter Reinholdtsen                      ){
928c18ec02fSPetter Reinholdtsen                         return_value = ipmi_ek_display_carrier_connectivity(
929c18ec02fSPetter Reinholdtsen                                                 list_record[num_file] );
930c18ec02fSPetter Reinholdtsen                }
931c18ec02fSPetter Reinholdtsen                else if ( list_record[num_file]->data[PICMG_ID_OFFSET]
932c18ec02fSPetter Reinholdtsen                            ==
933c18ec02fSPetter Reinholdtsen                          FRU_AMC_CARRIER_INFO
934c18ec02fSPetter Reinholdtsen                        ){
935c18ec02fSPetter Reinholdtsen                   /*Ref: See AMC.0 Specification Table 3-3: Carrier Information
936c18ec02fSPetter Reinholdtsen                   * Table about offset value
937c18ec02fSPetter Reinholdtsen                   */
938c18ec02fSPetter Reinholdtsen                   printf( "   Number of AMC bays supported by Carrier: %d\n",
939c18ec02fSPetter Reinholdtsen                           list_record[num_file]->data[START_DATA_OFFSET+1] );
940c18ec02fSPetter Reinholdtsen                }
941c18ec02fSPetter Reinholdtsen             }
942c18ec02fSPetter Reinholdtsen             /*Ref: AMC.0 Specification: Table 3-11
943c18ec02fSPetter Reinholdtsen             * Carrier Activation and Current Management Record
944c18ec02fSPetter Reinholdtsen             */
945c18ec02fSPetter Reinholdtsen             if ( list_record[num_file]->data[PICMG_ID_OFFSET]
946c18ec02fSPetter Reinholdtsen                   ==
947c18ec02fSPetter Reinholdtsen                  FRU_AMC_ACTIVATION
948c18ec02fSPetter Reinholdtsen                ){
949c18ec02fSPetter Reinholdtsen                int index_data = START_DATA_OFFSET;
950c18ec02fSPetter Reinholdtsen                struct fru_picmgext_carrier_activation_record car;
951c18ec02fSPetter Reinholdtsen                struct fru_picmgext_activation_record * cur_desc;
952c18ec02fSPetter Reinholdtsen 
953c18ec02fSPetter Reinholdtsen                memcpy ( &car, &list_record[num_file]->data[index_data],
954c18ec02fSPetter Reinholdtsen                      sizeof (struct fru_picmgext_carrier_activation_record) );
955c18ec02fSPetter Reinholdtsen                index_data +=
956c18ec02fSPetter Reinholdtsen                      sizeof (struct fru_picmgext_carrier_activation_record);
957c18ec02fSPetter Reinholdtsen                cur_desc = malloc (car.module_activation_record_count * \
958c18ec02fSPetter Reinholdtsen                      sizeof (struct fru_picmgext_activation_record) );
959c18ec02fSPetter Reinholdtsen                for(index=0; index<car.module_activation_record_count; index++){
960c18ec02fSPetter Reinholdtsen                   memcpy( &cur_desc[index],
961c18ec02fSPetter Reinholdtsen                            &list_record[num_file]->data[index_data],
962c18ec02fSPetter Reinholdtsen                            sizeof (struct fru_picmgext_activation_record) );
963c18ec02fSPetter Reinholdtsen 
964c18ec02fSPetter Reinholdtsen                   index_data += sizeof (struct fru_picmgext_activation_record);
965c18ec02fSPetter Reinholdtsen                }
966c18ec02fSPetter Reinholdtsen                /*Display the current*/
967c18ec02fSPetter Reinholdtsen                ipmi_ek_display_current_descriptor( car,
968c18ec02fSPetter Reinholdtsen                                     cur_desc, filename[num_file] );
969c18ec02fSPetter Reinholdtsen                free(cur_desc);
970c18ec02fSPetter Reinholdtsen                cur_desc = NULL;
971c18ec02fSPetter Reinholdtsen             }
972c18ec02fSPetter Reinholdtsen             /*Ref: AMC.0 specification, Table 3-10: Module Current Requirement*/
973c18ec02fSPetter Reinholdtsen             else if ( list_record[num_file]->data[PICMG_ID_OFFSET]
974c18ec02fSPetter Reinholdtsen                        == FRU_AMC_CURRENT
975c18ec02fSPetter Reinholdtsen                     ){
976c18ec02fSPetter Reinholdtsen                float power_in_watt = 0;
977c18ec02fSPetter Reinholdtsen                float current_in_amp = 0;
978c18ec02fSPetter Reinholdtsen 
979c18ec02fSPetter Reinholdtsen                printf("   %s power required (Current Draw): ",
980c18ec02fSPetter Reinholdtsen                   val2str ( file_type[num_file], ipmi_ekanalyzer_module_type) );
981c18ec02fSPetter Reinholdtsen                current_in_amp =
982c18ec02fSPetter Reinholdtsen                         list_record[num_file]->data[START_DATA_OFFSET]*0.1;
983c18ec02fSPetter Reinholdtsen                power_in_watt = current_in_amp * AMC_VOLTAGE;
984c18ec02fSPetter Reinholdtsen                printf("%.2f Watts (%.2f Amps)\n",power_in_watt, current_in_amp);
985c18ec02fSPetter Reinholdtsen             }
986c18ec02fSPetter Reinholdtsen          }
987c18ec02fSPetter Reinholdtsen          return_value = OK_STATUS;
988c18ec02fSPetter Reinholdtsen          /*Destroy the list of record*/
989c18ec02fSPetter Reinholdtsen          for ( index = 0; index < argc; index++ ){
990c18ec02fSPetter Reinholdtsen             while ( list_head[index] != NULL ){
991c18ec02fSPetter Reinholdtsen                ipmi_ek_remove_record_from_list ( list_head[index],
992c18ec02fSPetter Reinholdtsen                         &list_head[index],&list_last[index] );
993c18ec02fSPetter Reinholdtsen             }
994c18ec02fSPetter Reinholdtsen             if ( verbose > 1 )
995c18ec02fSPetter Reinholdtsen                printf("Record list has been removed successfully\n");
996c18ec02fSPetter Reinholdtsen          }
997c18ec02fSPetter Reinholdtsen       }
998c18ec02fSPetter Reinholdtsen    }
999c18ec02fSPetter Reinholdtsen    printf("%s\n", STAR_LINE_LIMITER);
1000c18ec02fSPetter Reinholdtsen    return return_value;
1001c18ec02fSPetter Reinholdtsen }
1002c18ec02fSPetter Reinholdtsen 
1003c18ec02fSPetter Reinholdtsen /**************************************************************************
1004c18ec02fSPetter Reinholdtsen *
1005c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_current_descriptor
1006c18ec02fSPetter Reinholdtsen *
1007c18ec02fSPetter Reinholdtsen * Description: Display the current descriptor under format xx Watts (xx Amps)
1008c18ec02fSPetter Reinholdtsen *
1009c18ec02fSPetter Reinholdtsen * Restriction: None
1010c18ec02fSPetter Reinholdtsen *
1011c18ec02fSPetter Reinholdtsen * Input: struct fru_picmgext_carrier_activation_record car: contain binary data
1012c18ec02fSPetter Reinholdtsen *                  of carrier activation record
1013c18ec02fSPetter Reinholdtsen *        struct fru_picmgext_activation_record * cur_desc: contain current
1014c18ec02fSPetter Reinholdtsen *                  descriptor
1015c18ec02fSPetter Reinholdtsen *        char* filename: strings that contained filename of FRU data binary file
1016c18ec02fSPetter Reinholdtsen *
1017c18ec02fSPetter Reinholdtsen * Output: None
1018c18ec02fSPetter Reinholdtsen *
1019c18ec02fSPetter Reinholdtsen * Global: None
1020c18ec02fSPetter Reinholdtsen *
1021c18ec02fSPetter Reinholdtsen * Return: None
1022c18ec02fSPetter Reinholdtsen *
1023c18ec02fSPetter Reinholdtsen ***************************************************************************/
1024c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_current_descriptor(struct fru_picmgext_carrier_activation_record car,struct fru_picmgext_activation_record * cur_desc,char * filename)1025c18ec02fSPetter Reinholdtsen ipmi_ek_display_current_descriptor(
1026c18ec02fSPetter Reinholdtsen 		struct fru_picmgext_carrier_activation_record car,
1027b37b9149SZdenek Styblik 		struct fru_picmgext_activation_record *cur_desc,
1028b37b9149SZdenek Styblik 		char *filename)
1029c18ec02fSPetter Reinholdtsen {
1030c18ec02fSPetter Reinholdtsen 	int index = 0;
1031c18ec02fSPetter Reinholdtsen 	float power_in_watt = 0.0;
1032c18ec02fSPetter Reinholdtsen 	float current_in_amp = 0.0;
1033c18ec02fSPetter Reinholdtsen 	for (index = 0; index < car.module_activation_record_count; index++) {
1034b37b9149SZdenek Styblik 		/* See AMC.0 specification, Table 3-12 for
1035b37b9149SZdenek Styblik 		 * detail about calculation
1036b37b9149SZdenek Styblik 		 */
1037c18ec02fSPetter Reinholdtsen 		current_in_amp = (float)cur_desc[index].max_module_curr * 0.1;
1038c18ec02fSPetter Reinholdtsen 		power_in_watt = (float)current_in_amp * AMC_VOLTAGE;
1039c18ec02fSPetter Reinholdtsen 		printf("   Carrier AMC power available on %s:\n",
1040b37b9149SZdenek Styblik 				val2str( cur_desc[index].ibmb_addr,
1041b37b9149SZdenek Styblik 					ipmi_ekanalyzer_IPMBL_addr));
1042b37b9149SZdenek Styblik 		printf("\t- Local IPMB Address    \t: %02x\n",
1043b37b9149SZdenek Styblik 				cur_desc[index].ibmb_addr);
1044c18ec02fSPetter Reinholdtsen 		printf("\t- Maximum module Current\t: %.2f Watts (%.2f Amps)\n",
1045c18ec02fSPetter Reinholdtsen 				power_in_watt, current_in_amp);
1046c18ec02fSPetter Reinholdtsen 	}
1047c18ec02fSPetter Reinholdtsen 	/* Display total power on Carrier */
1048c18ec02fSPetter Reinholdtsen 	current_in_amp =  (float)car.max_internal_curr * 0.1;
1049c18ec02fSPetter Reinholdtsen 	power_in_watt = (float)current_in_amp * AMC_VOLTAGE;
1050c18ec02fSPetter Reinholdtsen 	printf("   Carrier AMC total power available for all bays from file '%s':",
1051c18ec02fSPetter Reinholdtsen 			filename);
1052c18ec02fSPetter Reinholdtsen 	printf(" %.2f Watts (%.2f Amps)\n", power_in_watt, current_in_amp);
1053c18ec02fSPetter Reinholdtsen }
1054c18ec02fSPetter Reinholdtsen 
1055c18ec02fSPetter Reinholdtsen /**************************************************************************
1056c18ec02fSPetter Reinholdtsen *
1057c18ec02fSPetter Reinholdtsen * Function name: ipmi_ekanalyzer_ekeying_match
1058c18ec02fSPetter Reinholdtsen *
1059c18ec02fSPetter Reinholdtsen * Description: Check for possible Ekeying match between two FRU files
1060c18ec02fSPetter Reinholdtsen *
1061c18ec02fSPetter Reinholdtsen * Restriction: None
1062c18ec02fSPetter Reinholdtsen *
1063c18ec02fSPetter Reinholdtsen * Input: argc: number of the argument received
1064c18ec02fSPetter Reinholdtsen *        opt: string that contains display option received from user.
1065c18ec02fSPetter Reinholdtsen *        filename: strings that contained filename of FRU data binary file
1066c18ec02fSPetter Reinholdtsen *        file_type: a pointer that contain file type (on carrier file,
1067c18ec02fSPetter Reinholdtsen *                       a1 file, b1 file...)
1068c18ec02fSPetter Reinholdtsen *
1069c18ec02fSPetter Reinholdtsen * Output: None
1070c18ec02fSPetter Reinholdtsen *
1071c18ec02fSPetter Reinholdtsen * Global: None
1072c18ec02fSPetter Reinholdtsen *
1073c18ec02fSPetter Reinholdtsen * Return:   return TRUE on success and FALSE if the record doesn't exist.
1074c18ec02fSPetter Reinholdtsen *
1075c18ec02fSPetter Reinholdtsen ***************************************************************************/
1076c18ec02fSPetter Reinholdtsen static tboolean
ipmi_ekanalyzer_ekeying_match(int argc,char * opt,char ** filename,int * file_type)1077c18ec02fSPetter Reinholdtsen ipmi_ekanalyzer_ekeying_match( int argc, char * opt,
1078c18ec02fSPetter Reinholdtsen          char ** filename, int * file_type )
1079c18ec02fSPetter Reinholdtsen {
1080c18ec02fSPetter Reinholdtsen    tboolean return_value = FALSE;
1081c18ec02fSPetter Reinholdtsen 
1082c18ec02fSPetter Reinholdtsen    if ( (strcmp(opt, "carrier") == 0 ) || (strcmp(opt, "power") == 0) ){
1083c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "   ekanalyzer summary [match/ unmatch/ all]"\
1084c18ec02fSPetter Reinholdtsen                    " <xx=frufile> <xx=frufile> [xx=frufile]");
1085c18ec02fSPetter Reinholdtsen       return_value = ERROR_STATUS;
1086c18ec02fSPetter Reinholdtsen    }
1087c18ec02fSPetter Reinholdtsen    else{
1088c18ec02fSPetter Reinholdtsen       int num_file=0;
1089c18ec02fSPetter Reinholdtsen       tboolean amc_file = FALSE; /*used to indicate the present of AMC file*/
1090c18ec02fSPetter Reinholdtsen       tboolean oc_file = FALSE; /*used to indicate the present of Carrier file*/
1091c18ec02fSPetter Reinholdtsen 
1092c18ec02fSPetter Reinholdtsen       /*Check for possible ekeying match between files*/
1093c18ec02fSPetter Reinholdtsen       for ( num_file=0; num_file < argc; num_file++ ){
1094c18ec02fSPetter Reinholdtsen          if ( ( file_type[num_file] == ON_CARRIER_FRU_FILE )
1095c18ec02fSPetter Reinholdtsen               || ( file_type[num_file] == CONFIG_FILE )
1096c18ec02fSPetter Reinholdtsen               || ( file_type[num_file] == SHELF_MANAGER_FRU_FILE )
1097c18ec02fSPetter Reinholdtsen             ){
1098c18ec02fSPetter Reinholdtsen             amc_file = FALSE;
1099c18ec02fSPetter Reinholdtsen          }
1100c18ec02fSPetter Reinholdtsen          else {   /*there is an amc file*/
1101c18ec02fSPetter Reinholdtsen             amc_file = TRUE;
1102c18ec02fSPetter Reinholdtsen             break;
1103c18ec02fSPetter Reinholdtsen          }
1104c18ec02fSPetter Reinholdtsen       }
1105c18ec02fSPetter Reinholdtsen       if ( amc_file == FALSE ){
1106c18ec02fSPetter Reinholdtsen          printf("\nNo AMC FRU file is provided --->" \
1107c18ec02fSPetter Reinholdtsen                        " No possible ekeying match!\n");
1108c18ec02fSPetter Reinholdtsen          return_value = ERROR_STATUS;
1109c18ec02fSPetter Reinholdtsen       }
1110c18ec02fSPetter Reinholdtsen       else{
1111c18ec02fSPetter Reinholdtsen          /*If no carrier file is provided, return error*/
1112c18ec02fSPetter Reinholdtsen          for ( num_file=0; num_file < argc; num_file++ ){
1113c18ec02fSPetter Reinholdtsen             if ( (file_type[num_file] == ON_CARRIER_FRU_FILE )
1114c18ec02fSPetter Reinholdtsen                  || ( file_type[num_file] == CONFIG_FILE )
1115c18ec02fSPetter Reinholdtsen                  || ( file_type[num_file] == SHELF_MANAGER_FRU_FILE )
1116c18ec02fSPetter Reinholdtsen                ){
1117c18ec02fSPetter Reinholdtsen                oc_file = TRUE;
1118c18ec02fSPetter Reinholdtsen                break;
1119c18ec02fSPetter Reinholdtsen             }
1120c18ec02fSPetter Reinholdtsen          }
1121c18ec02fSPetter Reinholdtsen          if ( !oc_file ){
1122c18ec02fSPetter Reinholdtsen             printf("\nNo Carrier FRU file is provided" \
1123c18ec02fSPetter Reinholdtsen                         " ---> No possible ekeying match!\n");
1124c18ec02fSPetter Reinholdtsen             return_value = ERROR_STATUS;
1125c18ec02fSPetter Reinholdtsen          }
1126c18ec02fSPetter Reinholdtsen          else{
1127c18ec02fSPetter Reinholdtsen             /*list des multi record*/
1128c18ec02fSPetter Reinholdtsen             struct ipmi_ek_multi_header * list_head[argc];
1129c18ec02fSPetter Reinholdtsen             struct ipmi_ek_multi_header * list_record[argc];
1130c18ec02fSPetter Reinholdtsen             struct ipmi_ek_multi_header * list_last[argc];
1131c18ec02fSPetter Reinholdtsen             struct ipmi_ek_multi_header * pcarrier_p2p;
1132c18ec02fSPetter Reinholdtsen             int list = 0;
1133c18ec02fSPetter Reinholdtsen             int match_pair = 0;
1134c18ec02fSPetter Reinholdtsen 
1135c18ec02fSPetter Reinholdtsen             /*Create an empty list*/
1136c18ec02fSPetter Reinholdtsen             for ( list=0; list<argc; list++ ){
1137c18ec02fSPetter Reinholdtsen                list_head[list] = NULL;
1138c18ec02fSPetter Reinholdtsen                list_record[list] = NULL;
1139c18ec02fSPetter Reinholdtsen                list_last[list] = NULL;
1140c18ec02fSPetter Reinholdtsen             }
1141c18ec02fSPetter Reinholdtsen             list=0;
1142c18ec02fSPetter Reinholdtsen 
1143c18ec02fSPetter Reinholdtsen             for ( num_file=0; num_file < argc; num_file++ ){
1144c18ec02fSPetter Reinholdtsen                if (file_type[num_file] != CONFIG_FILE){
1145c18ec02fSPetter Reinholdtsen                   return_value = ipmi_ekanalyzer_fru_file2structure(
1146c18ec02fSPetter Reinholdtsen                                 filename[num_file], &list_head[num_file],
1147c18ec02fSPetter Reinholdtsen                                 &list_record[num_file], &list_last[num_file]);
1148c18ec02fSPetter Reinholdtsen                }
1149c18ec02fSPetter Reinholdtsen             }
1150c18ec02fSPetter Reinholdtsen             /*Get Carrier p2p connectivity record for physical check*/
1151c18ec02fSPetter Reinholdtsen             for (num_file=0; num_file < argc; num_file++){
1152c18ec02fSPetter Reinholdtsen                if (file_type[num_file] == ON_CARRIER_FRU_FILE ){
1153c18ec02fSPetter Reinholdtsen                   for ( pcarrier_p2p=list_head[num_file];
1154c18ec02fSPetter Reinholdtsen                         pcarrier_p2p != NULL ;
1155c18ec02fSPetter Reinholdtsen                         pcarrier_p2p = pcarrier_p2p->next
1156c18ec02fSPetter Reinholdtsen                      ){
1157c18ec02fSPetter Reinholdtsen                      if ( pcarrier_p2p->data[PICMG_ID_OFFSET]
1158c18ec02fSPetter Reinholdtsen                            == FRU_AMC_CARRIER_P2P
1159c18ec02fSPetter Reinholdtsen                         ){
1160c18ec02fSPetter Reinholdtsen                         break;
1161c18ec02fSPetter Reinholdtsen                      }
1162c18ec02fSPetter Reinholdtsen                   }
1163c18ec02fSPetter Reinholdtsen                   break;
1164c18ec02fSPetter Reinholdtsen                }
1165c18ec02fSPetter Reinholdtsen             }
1166c18ec02fSPetter Reinholdtsen             /*Determine the match making pair*/
1167c18ec02fSPetter Reinholdtsen             while ( match_pair < argc ){
1168c18ec02fSPetter Reinholdtsen                for ( num_file = (match_pair+1); num_file<argc; num_file++ ){
1169c18ec02fSPetter Reinholdtsen                   if ( ( file_type[match_pair] != CONFIG_FILE )
1170c18ec02fSPetter Reinholdtsen                         && ( file_type[num_file] != CONFIG_FILE )
1171c18ec02fSPetter Reinholdtsen                      ){
1172c18ec02fSPetter Reinholdtsen                      if ( ( file_type[match_pair] != ON_CARRIER_FRU_FILE )
1173c18ec02fSPetter Reinholdtsen                            || ( file_type[num_file] != ON_CARRIER_FRU_FILE )
1174c18ec02fSPetter Reinholdtsen                         ){
1175c18ec02fSPetter Reinholdtsen                         printf("%s vs %s\n",
1176c18ec02fSPetter Reinholdtsen                                  val2str(file_type[match_pair],
1177c18ec02fSPetter Reinholdtsen                                                 ipmi_ekanalyzer_module_type),
1178c18ec02fSPetter Reinholdtsen                                  val2str(file_type[num_file],
1179c18ec02fSPetter Reinholdtsen                                                 ipmi_ekanalyzer_module_type));
1180c18ec02fSPetter Reinholdtsen                         /*Ekeying match between 2 files*/
1181c18ec02fSPetter Reinholdtsen                         if (verbose>0){
1182c18ec02fSPetter Reinholdtsen                            printf("Start matching process\n");
1183c18ec02fSPetter Reinholdtsen                         }
1184c18ec02fSPetter Reinholdtsen                         return_value = ipmi_ek_matching_process( file_type,
1185c18ec02fSPetter Reinholdtsen                                              match_pair, num_file, list_head,
1186c18ec02fSPetter Reinholdtsen                                              list_last, opt, pcarrier_p2p);
1187c18ec02fSPetter Reinholdtsen                      }
1188c18ec02fSPetter Reinholdtsen                   }
1189c18ec02fSPetter Reinholdtsen                }
1190c18ec02fSPetter Reinholdtsen                match_pair ++;
1191c18ec02fSPetter Reinholdtsen             }
1192c18ec02fSPetter Reinholdtsen             for( num_file=0; num_file < argc; num_file++ ){
1193c18ec02fSPetter Reinholdtsen                if (list_head[num_file] != NULL ){
1194c18ec02fSPetter Reinholdtsen                   ipmi_ek_remove_record_from_list( list_head[num_file],
1195c18ec02fSPetter Reinholdtsen                            &list_record[num_file], &list_last[num_file]);
1196c18ec02fSPetter Reinholdtsen                }
1197c18ec02fSPetter Reinholdtsen                if ( ( num_file == argc-1 ) && verbose )
1198c18ec02fSPetter Reinholdtsen                   printf("Record list has been removed successfully\n");
1199c18ec02fSPetter Reinholdtsen             }
1200c18ec02fSPetter Reinholdtsen             return_value = OK_STATUS;
1201c18ec02fSPetter Reinholdtsen          }
1202c18ec02fSPetter Reinholdtsen       }
1203c18ec02fSPetter Reinholdtsen    }
1204c18ec02fSPetter Reinholdtsen    return return_value;
1205c18ec02fSPetter Reinholdtsen }
1206c18ec02fSPetter Reinholdtsen 
1207c18ec02fSPetter Reinholdtsen /**************************************************************************
1208c18ec02fSPetter Reinholdtsen *
1209c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_matching_process
1210c18ec02fSPetter Reinholdtsen *
1211c18ec02fSPetter Reinholdtsen * Description: This function process the OEM check, Physical Connectivity check,
1212c18ec02fSPetter Reinholdtsen *              and Link Descriptor comparison to do Ekeying match
1213c18ec02fSPetter Reinholdtsen *
1214c18ec02fSPetter Reinholdtsen * Restriction: None
1215c18ec02fSPetter Reinholdtsen *
1216c18ec02fSPetter Reinholdtsen * Input: file_type: a pointer that contain file type (on carrier file,
1217c18ec02fSPetter Reinholdtsen *                       a1 file, b1 file...)
1218c18ec02fSPetter Reinholdtsen *        index1: position of the first record in the list of the record
1219c18ec02fSPetter Reinholdtsen *        index2: position of the second record in the list of the record
1220c18ec02fSPetter Reinholdtsen *        ipmi_ek_multi_header ** list_head: pointer to the header of a
1221c18ec02fSPetter Reinholdtsen *                 linked list that contain FRU multi record
1222c18ec02fSPetter Reinholdtsen *        ipmi_ek_multi_header ** list_last: pointer to the tale of a
1223c18ec02fSPetter Reinholdtsen *                 linked list that contain FRU multi record
1224c18ec02fSPetter Reinholdtsen *        opt: string that contain display option such as "match", "unmatch", or
1225c18ec02fSPetter Reinholdtsen *               "all".
1226c18ec02fSPetter Reinholdtsen *        pphysical: a pointer that contain a carrier p2p connectivity record
1227c18ec02fSPetter Reinholdtsen *                   to perform physical check
1228c18ec02fSPetter Reinholdtsen *
1229c18ec02fSPetter Reinholdtsen * Output: None
1230c18ec02fSPetter Reinholdtsen *
1231c18ec02fSPetter Reinholdtsen * Global: None
1232c18ec02fSPetter Reinholdtsen *
1233c18ec02fSPetter Reinholdtsen * Return:   return OK_STATUS on success and ERROR_STATUS if the record doesn't
1234c18ec02fSPetter Reinholdtsen *           exist.
1235c18ec02fSPetter Reinholdtsen *
1236c18ec02fSPetter Reinholdtsen ***************************************************************************/
ipmi_ek_matching_process(int * file_type,int index1,int index2,struct ipmi_ek_multi_header ** list_head,struct ipmi_ek_multi_header ** list_last,char * opt,struct ipmi_ek_multi_header * pphysical)1237c18ec02fSPetter Reinholdtsen static int ipmi_ek_matching_process( int * file_type, int index1, int index2,
1238c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header ** list_head,
1239c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header ** list_last, char * opt,
1240c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * pphysical )
1241c18ec02fSPetter Reinholdtsen {
1242c18ec02fSPetter Reinholdtsen    int result = ERROR_STATUS;
1243c18ec02fSPetter Reinholdtsen    struct ipmi_ek_multi_header * record;
1244c18ec02fSPetter Reinholdtsen    int num_amc_record1 = 0;/*Number of AMC records in the first module*/
1245c18ec02fSPetter Reinholdtsen    int num_amc_record2 = 0;/*Number of AMC records in the second module*/
1246c18ec02fSPetter Reinholdtsen 
1247c18ec02fSPetter Reinholdtsen    /* Comparison between an On-Carrier and an AMC*/
1248c18ec02fSPetter Reinholdtsen    if ( file_type[index2] == ON_CARRIER_FRU_FILE ){
1249c18ec02fSPetter Reinholdtsen       int index_temp = 0;
1250c18ec02fSPetter Reinholdtsen       index_temp = index1;
1251c18ec02fSPetter Reinholdtsen       index1 = index2; /*index1 indicate on carrier*/
1252c18ec02fSPetter Reinholdtsen       index2 = index_temp; /*index2 indcate an AMC*/
1253c18ec02fSPetter Reinholdtsen    }
1254c18ec02fSPetter Reinholdtsen    /*Calculate record size for Carrier file*/
1255c18ec02fSPetter Reinholdtsen    for ( record=list_head[index1]; record != NULL;record = record->next ){
1256c18ec02fSPetter Reinholdtsen       if ( record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){
1257c18ec02fSPetter Reinholdtsen          num_amc_record2++;
1258c18ec02fSPetter Reinholdtsen       }
1259c18ec02fSPetter Reinholdtsen    }
1260c18ec02fSPetter Reinholdtsen    /*Calculate record size for amc file*/
1261c18ec02fSPetter Reinholdtsen    for ( record=list_head[index2]; record != NULL;record = record->next){
1262c18ec02fSPetter Reinholdtsen       if ( record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){
1263c18ec02fSPetter Reinholdtsen          num_amc_record1++;
1264c18ec02fSPetter Reinholdtsen       }
1265c18ec02fSPetter Reinholdtsen    }
1266c18ec02fSPetter Reinholdtsen    if ( (num_amc_record1 > 0) && (num_amc_record2 > 0) ){
1267c18ec02fSPetter Reinholdtsen       int index_record1 = 0;
1268c18ec02fSPetter Reinholdtsen       int index_record2 = 0;
1269c18ec02fSPetter Reinholdtsen       /* Multi records of AMC module */
1270c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record * amc_record1 = NULL;
1271c18ec02fSPetter Reinholdtsen       /* Multi records of Carrier or an AMC module */
1272c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record * amc_record2 = NULL;
1273c18ec02fSPetter Reinholdtsen 
1274c18ec02fSPetter Reinholdtsen       amc_record1 = malloc ( num_amc_record1 * \
1275c18ec02fSPetter Reinholdtsen                            sizeof(struct ipmi_ek_amc_p2p_connectivity_record));
1276c18ec02fSPetter Reinholdtsen       amc_record2 = malloc ( num_amc_record2 * \
1277c18ec02fSPetter Reinholdtsen                            sizeof(struct ipmi_ek_amc_p2p_connectivity_record));
1278c18ec02fSPetter Reinholdtsen 
1279c18ec02fSPetter Reinholdtsen       for (record=list_head[index2]; record != NULL;record = record->next){
1280c18ec02fSPetter Reinholdtsen          if ( record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){
1281c18ec02fSPetter Reinholdtsen             result = ipmi_ek_create_amc_p2p_record( record,
1282c18ec02fSPetter Reinholdtsen                                        &amc_record1[index_record1] );
1283c18ec02fSPetter Reinholdtsen             if (result != ERROR_STATUS){
1284c18ec02fSPetter Reinholdtsen                struct ipmi_ek_multi_header * current_record = NULL;
1285c18ec02fSPetter Reinholdtsen 
1286c18ec02fSPetter Reinholdtsen                for ( current_record=list_head[index1];
1287c18ec02fSPetter Reinholdtsen                      current_record != NULL ;
1288c18ec02fSPetter Reinholdtsen                      current_record = current_record->next
1289c18ec02fSPetter Reinholdtsen                   ){
1290c18ec02fSPetter Reinholdtsen                   if ( current_record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){
1291c18ec02fSPetter Reinholdtsen                      result = ipmi_ek_create_amc_p2p_record( current_record,
1292c18ec02fSPetter Reinholdtsen                                        &amc_record2[index_record2] );
1293c18ec02fSPetter Reinholdtsen                      if ( result != ERROR_STATUS ){
1294c18ec02fSPetter Reinholdtsen                         if ( result == OK_STATUS ){
1295c18ec02fSPetter Reinholdtsen                            /*Compare Link descriptor*/
1296c18ec02fSPetter Reinholdtsen                            result = ipmi_ek_compare_link ( pphysical,
1297c18ec02fSPetter Reinholdtsen                                     amc_record1[index_record1],
1298c18ec02fSPetter Reinholdtsen                                     amc_record2[index_record2],
1299c18ec02fSPetter Reinholdtsen                                     opt, file_type[index1], file_type[index2]);
1300c18ec02fSPetter Reinholdtsen                         }
1301c18ec02fSPetter Reinholdtsen                         index_record2++;
1302c18ec02fSPetter Reinholdtsen                      }
1303c18ec02fSPetter Reinholdtsen                   } /*end of FRU_AMC_P2P */
1304c18ec02fSPetter Reinholdtsen                } /* end of for loop */
1305c18ec02fSPetter Reinholdtsen                index_record1++;
1306c18ec02fSPetter Reinholdtsen             }
1307c18ec02fSPetter Reinholdtsen          }
1308c18ec02fSPetter Reinholdtsen       }
1309c18ec02fSPetter Reinholdtsen       free(amc_record1) ;
1310c18ec02fSPetter Reinholdtsen       amc_record1 = NULL;
1311c18ec02fSPetter Reinholdtsen       free(amc_record2) ;
1312c18ec02fSPetter Reinholdtsen       amc_record2 = NULL;
1313c18ec02fSPetter Reinholdtsen    }
1314c18ec02fSPetter Reinholdtsen    else{
1315c18ec02fSPetter Reinholdtsen       printf("No amc record is found!\n");
1316c18ec02fSPetter Reinholdtsen    }
1317c18ec02fSPetter Reinholdtsen 
1318c18ec02fSPetter Reinholdtsen    return result;
1319c18ec02fSPetter Reinholdtsen }
1320c18ec02fSPetter Reinholdtsen 
1321c18ec02fSPetter Reinholdtsen /**************************************************************************
1322c18ec02fSPetter Reinholdtsen *
1323c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_check_physical_connectivity
1324c18ec02fSPetter Reinholdtsen *
1325c18ec02fSPetter Reinholdtsen * Description: This function check for point to point connectivity between
1326c18ec02fSPetter Reinholdtsen *               two modules by comparing each enable port in link descriptor
1327c18ec02fSPetter Reinholdtsen *               with local and remote ports of port descriptor in
1328c18ec02fSPetter Reinholdtsen *               carrier point-to-point connectivity record according to the
1329c18ec02fSPetter Reinholdtsen *               corresponding file type ( a1, b1, b2...).
1330c18ec02fSPetter Reinholdtsen *
1331c18ec02fSPetter Reinholdtsen * Restriction: In order to perform physical check connectivity, it needs to
1332c18ec02fSPetter Reinholdtsen *               compare between 2 AMC Modules, so the use of index ( 1 and 2 )
1333c18ec02fSPetter Reinholdtsen *               can facilitate the comparison in this case.
1334c18ec02fSPetter Reinholdtsen *
1335c18ec02fSPetter Reinholdtsen * Input: record1: is an AMC p2p record for an AMC module
1336c18ec02fSPetter Reinholdtsen *        record2 is an AMC p2p record for an On-Carrier record or an AMC module
1337c18ec02fSPetter Reinholdtsen *        char* opt: option string that will tell if a matching result, unmatched
1338c18ec02fSPetter Reinholdtsen *                 result or all the results will be displayed.
1339c18ec02fSPetter Reinholdtsen *        file_type1: indicates type of the first module
1340c18ec02fSPetter Reinholdtsen *        file_type2: indicates type of the second module
1341c18ec02fSPetter Reinholdtsen *
1342c18ec02fSPetter Reinholdtsen * Output: None
1343c18ec02fSPetter Reinholdtsen *
1344c18ec02fSPetter Reinholdtsen * Global: None
1345c18ec02fSPetter Reinholdtsen *
1346c18ec02fSPetter Reinholdtsen * Return:   return OK_STATUS if both link are matched, otherwise
1347c18ec02fSPetter Reinholdtsen *            return ERROR_STATUS
1348c18ec02fSPetter Reinholdtsen *
1349c18ec02fSPetter Reinholdtsen ***************************************************************************/
1350c18ec02fSPetter Reinholdtsen static int
ipmi_ek_check_physical_connectivity(struct ipmi_ek_amc_p2p_connectivity_record record1,int index1,struct ipmi_ek_amc_p2p_connectivity_record record2,int index2,struct ipmi_ek_multi_header * record,int filetype1,int filetype2,char * option)1351c18ec02fSPetter Reinholdtsen ipmi_ek_check_physical_connectivity(
1352c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record record1, int index1,
1353c18ec02fSPetter Reinholdtsen       struct ipmi_ek_amc_p2p_connectivity_record record2, int index2,
1354c18ec02fSPetter Reinholdtsen       struct ipmi_ek_multi_header * record,
1355c18ec02fSPetter Reinholdtsen       int filetype1, int filetype2, char * option )
1356c18ec02fSPetter Reinholdtsen {
1357c18ec02fSPetter Reinholdtsen    int return_status = OK_STATUS;
1358c18ec02fSPetter Reinholdtsen 
1359c18ec02fSPetter Reinholdtsen    if ( record == NULL ){
1360c18ec02fSPetter Reinholdtsen       printf("NO Carrier p2p connectivity !\n");
1361c18ec02fSPetter Reinholdtsen       return_status = ERROR_STATUS;
1362c18ec02fSPetter Reinholdtsen    }
1363c18ec02fSPetter Reinholdtsen    else{
1364c18ec02fSPetter Reinholdtsen       #define INVALID_AMC_SITE_NUMBER      -1
1365c18ec02fSPetter Reinholdtsen       int index = START_DATA_OFFSET;
1366c18ec02fSPetter Reinholdtsen       int amc_site = INVALID_AMC_SITE_NUMBER;
1367c18ec02fSPetter Reinholdtsen       struct fru_picmgext_carrier_p2p_record rsc_desc;
1368c18ec02fSPetter Reinholdtsen       struct fru_picmgext_carrier_p2p_descriptor * port_desc = NULL;
1369c18ec02fSPetter Reinholdtsen 
1370c18ec02fSPetter Reinholdtsen       /* Get the physical connectivity record */
1371c18ec02fSPetter Reinholdtsen       while ( index < record->header.len ) {
1372c18ec02fSPetter Reinholdtsen          rsc_desc.resource_id = record->data[index++];
1373c18ec02fSPetter Reinholdtsen          rsc_desc.p2p_count = record->data[index++];
1374c18ec02fSPetter Reinholdtsen          /* carrier p2p record starts with on-carrier device */
1375c18ec02fSPetter Reinholdtsen          if ( (rsc_desc.resource_id == record1.rsc_id)
1376c18ec02fSPetter Reinholdtsen                ||
1377c18ec02fSPetter Reinholdtsen               (rsc_desc.resource_id == record2.rsc_id)
1378c18ec02fSPetter Reinholdtsen             ){
1379c18ec02fSPetter Reinholdtsen             if (rsc_desc.p2p_count <= 0){
1380c18ec02fSPetter Reinholdtsen                printf("No p2p count\n");
1381c18ec02fSPetter Reinholdtsen                return_status = ERROR_STATUS;
1382c18ec02fSPetter Reinholdtsen             }
1383c18ec02fSPetter Reinholdtsen             else{
1384c18ec02fSPetter Reinholdtsen                port_desc = malloc ( rsc_desc.p2p_count *
1385c18ec02fSPetter Reinholdtsen                            sizeof(struct fru_picmgext_carrier_p2p_descriptor) );
1386c18ec02fSPetter Reinholdtsen                index = ipmi_ek_get_resource_descriptor( rsc_desc.p2p_count,
1387c18ec02fSPetter Reinholdtsen                            index, port_desc, record );
1388c18ec02fSPetter Reinholdtsen                amc_site = INVALID_AMC_SITE_NUMBER;
1389c18ec02fSPetter Reinholdtsen                break;
1390c18ec02fSPetter Reinholdtsen             }
1391c18ec02fSPetter Reinholdtsen          }
1392c18ec02fSPetter Reinholdtsen          else{ /* carrier p2p record starts with AMC module */
1393c18ec02fSPetter Reinholdtsen             if (rsc_desc.resource_id == AMC_MODULE){
1394c18ec02fSPetter Reinholdtsen                if (filetype1 != ON_CARRIER_FRU_FILE){
1395c18ec02fSPetter Reinholdtsen                   amc_site = filetype1;
1396c18ec02fSPetter Reinholdtsen                }
1397c18ec02fSPetter Reinholdtsen                else{
1398c18ec02fSPetter Reinholdtsen                   amc_site = filetype2;
1399c18ec02fSPetter Reinholdtsen                }
1400c18ec02fSPetter Reinholdtsen             }
1401c18ec02fSPetter Reinholdtsen             else{
1402c18ec02fSPetter Reinholdtsen                amc_site = rsc_desc.resource_id & 0x0f;
1403c18ec02fSPetter Reinholdtsen             }
1404c18ec02fSPetter Reinholdtsen             if ( amc_site > 0 ){
1405c18ec02fSPetter Reinholdtsen                if ( (amc_site == filetype1) || (amc_site == filetype2) ){
1406c18ec02fSPetter Reinholdtsen                   port_desc = malloc ( rsc_desc.p2p_count *
1407c18ec02fSPetter Reinholdtsen                            sizeof(struct fru_picmgext_carrier_p2p_descriptor) );
1408c18ec02fSPetter Reinholdtsen                   index = ipmi_ek_get_resource_descriptor( rsc_desc.p2p_count,
1409c18ec02fSPetter Reinholdtsen                                     index, port_desc, record );
1410c18ec02fSPetter Reinholdtsen                   break;
1411c18ec02fSPetter Reinholdtsen                }
1412c18ec02fSPetter Reinholdtsen             }
1413c18ec02fSPetter Reinholdtsen             else{
1414c18ec02fSPetter Reinholdtsen                return_status = ERROR_STATUS;
1415c18ec02fSPetter Reinholdtsen             }
1416c18ec02fSPetter Reinholdtsen          }
1417c18ec02fSPetter Reinholdtsen          /*If the record doesn't contain the same AMC site number in command
1418c18ec02fSPetter Reinholdtsen          * line, go to the next record
1419c18ec02fSPetter Reinholdtsen          */
1420c18ec02fSPetter Reinholdtsen          index += ( sizeof(struct fru_picmgext_carrier_p2p_descriptor) *
1421c18ec02fSPetter Reinholdtsen                      rsc_desc.p2p_count );
1422c18ec02fSPetter Reinholdtsen       }
1423c18ec02fSPetter Reinholdtsen 
1424c18ec02fSPetter Reinholdtsen       if ( (port_desc != NULL) && (return_status != ERROR_STATUS) ){
1425c18ec02fSPetter Reinholdtsen          int j=0;
1426c18ec02fSPetter Reinholdtsen 
1427c18ec02fSPetter Reinholdtsen          for ( j = 0; j < rsc_desc.p2p_count; j++ ){
1428c18ec02fSPetter Reinholdtsen             /* Compare only enable channel descriptor */
1429c18ec02fSPetter Reinholdtsen             if ( record1.ch_desc[index1].lane0port != DISABLE_PORT ){
1430c18ec02fSPetter Reinholdtsen                /* matching result from channel descriptor comparison */
1431c18ec02fSPetter Reinholdtsen                tboolean match_lane = FALSE;
1432c18ec02fSPetter Reinholdtsen 
1433c18ec02fSPetter Reinholdtsen                match_lane = ipmi_ek_compare_channel_descriptor (
1434c18ec02fSPetter Reinholdtsen                               record1.ch_desc[index1], record2.ch_desc[index2],
1435c18ec02fSPetter Reinholdtsen                               port_desc, j, rsc_desc.resource_id );
1436c18ec02fSPetter Reinholdtsen 
1437c18ec02fSPetter Reinholdtsen                if ( match_lane ){
1438c18ec02fSPetter Reinholdtsen                   if ( filetype1 != ON_CARRIER_FRU_FILE ){
1439c18ec02fSPetter Reinholdtsen                      if ( (
1440c18ec02fSPetter Reinholdtsen                            (filetype1 == (rsc_desc.resource_id & 0x0f))
1441c18ec02fSPetter Reinholdtsen                               &&
1442c18ec02fSPetter Reinholdtsen                            (filetype2 ==(port_desc[j].remote_resource_id &0x0f))
1443c18ec02fSPetter Reinholdtsen                           )
1444c18ec02fSPetter Reinholdtsen                           ||
1445c18ec02fSPetter Reinholdtsen                           (
1446c18ec02fSPetter Reinholdtsen                            (filetype2 == (rsc_desc.resource_id & 0x0f))
1447c18ec02fSPetter Reinholdtsen                               &&
1448c18ec02fSPetter Reinholdtsen                            (filetype1 ==(port_desc[j].remote_resource_id &0x0f))
1449c18ec02fSPetter Reinholdtsen                           )
1450c18ec02fSPetter Reinholdtsen                         ){
1451c18ec02fSPetter Reinholdtsen                         if ( ! (strcmp(option, "unmatch") == 0) ){
1452c18ec02fSPetter Reinholdtsen                            printf("%s port %d ==> %s port %d\n",
1453c18ec02fSPetter Reinholdtsen                               val2str(filetype2, ipmi_ekanalyzer_module_type),
1454c18ec02fSPetter Reinholdtsen                               record1.ch_desc[index1].lane0port,
1455c18ec02fSPetter Reinholdtsen                               val2str(filetype1, ipmi_ekanalyzer_module_type),
1456c18ec02fSPetter Reinholdtsen                               record2.ch_desc[index2].lane0port);
1457c18ec02fSPetter Reinholdtsen                         }
1458c18ec02fSPetter Reinholdtsen                         return_status = OK_STATUS;
1459c18ec02fSPetter Reinholdtsen 
1460c18ec02fSPetter Reinholdtsen                         break;
1461c18ec02fSPetter Reinholdtsen                      }
1462c18ec02fSPetter Reinholdtsen                      else{
1463c18ec02fSPetter Reinholdtsen                         if (verbose == LOG_DEBUG){
1464c18ec02fSPetter Reinholdtsen                            printf("No point 2 point connectivity\n");
1465c18ec02fSPetter Reinholdtsen                         }
1466c18ec02fSPetter Reinholdtsen                         return_status = ERROR_STATUS;
1467c18ec02fSPetter Reinholdtsen                      }
1468c18ec02fSPetter Reinholdtsen                   }
1469c18ec02fSPetter Reinholdtsen                   else{
1470c18ec02fSPetter Reinholdtsen                      if ( (record2.rsc_id == (rsc_desc.resource_id) )
1471c18ec02fSPetter Reinholdtsen                            &&
1472c18ec02fSPetter Reinholdtsen                          (filetype2 == (port_desc[j].remote_resource_id & 0x0f))
1473c18ec02fSPetter Reinholdtsen                         ){
1474c18ec02fSPetter Reinholdtsen                         if ( ! (strcmp(option, "unmatch") == 0) ){
1475c18ec02fSPetter Reinholdtsen                            printf("%s port %d ==> %s port %d\n",
1476c18ec02fSPetter Reinholdtsen                               val2str(filetype2, ipmi_ekanalyzer_module_type),
1477c18ec02fSPetter Reinholdtsen                               record1.ch_desc[index1].lane0port,
1478c18ec02fSPetter Reinholdtsen                               val2str(filetype1, ipmi_ekanalyzer_module_type),
1479c18ec02fSPetter Reinholdtsen                               record2.ch_desc[index2].lane0port);
1480c18ec02fSPetter Reinholdtsen                         }
1481c18ec02fSPetter Reinholdtsen                         return_status = OK_STATUS;
1482c18ec02fSPetter Reinholdtsen                         break;
1483c18ec02fSPetter Reinholdtsen                      }
1484c18ec02fSPetter Reinholdtsen                      else if ( (filetype2 == (rsc_desc.resource_id & 0x0f) )
1485c18ec02fSPetter Reinholdtsen                               &&
1486c18ec02fSPetter Reinholdtsen                            (record2.rsc_id == (port_desc[j].remote_resource_id))
1487c18ec02fSPetter Reinholdtsen                         ){
1488c18ec02fSPetter Reinholdtsen                         if ( ! (strcmp(option, "unmatch") == 0) ){
1489c18ec02fSPetter Reinholdtsen                            printf("%s port %d ==> %s %x port %d\n",
1490c18ec02fSPetter Reinholdtsen                               val2str(filetype2, ipmi_ekanalyzer_module_type),
1491c18ec02fSPetter Reinholdtsen                               record1.ch_desc[index1].lane0port,
1492c18ec02fSPetter Reinholdtsen                               val2str(filetype1, ipmi_ekanalyzer_module_type),
1493c18ec02fSPetter Reinholdtsen                               record2.rsc_id,record2.ch_desc[index2].lane0port);
1494c18ec02fSPetter Reinholdtsen                         }
1495c18ec02fSPetter Reinholdtsen                         return_status = OK_STATUS;
1496c18ec02fSPetter Reinholdtsen                         break;
1497c18ec02fSPetter Reinholdtsen                      }
1498c18ec02fSPetter Reinholdtsen                      else{
1499c18ec02fSPetter Reinholdtsen                         if (verbose == LOG_DEBUG){
1500c18ec02fSPetter Reinholdtsen                            printf("No point 2 point connectivity\n");
1501c18ec02fSPetter Reinholdtsen                         }
1502c18ec02fSPetter Reinholdtsen                         return_status = ERROR_STATUS;
1503c18ec02fSPetter Reinholdtsen                      }
1504c18ec02fSPetter Reinholdtsen                   }
1505c18ec02fSPetter Reinholdtsen                }
1506c18ec02fSPetter Reinholdtsen                else{
1507c18ec02fSPetter Reinholdtsen                   if (verbose == LOG_DEBUG){
1508c18ec02fSPetter Reinholdtsen                            printf("No point 2 point connectivity\n");
1509c18ec02fSPetter Reinholdtsen                   }
1510c18ec02fSPetter Reinholdtsen                   return_status = ERROR_STATUS;
1511c18ec02fSPetter Reinholdtsen                }
1512c18ec02fSPetter Reinholdtsen             }
1513c18ec02fSPetter Reinholdtsen             else{ /*If the link is disable, the result is always true*/
1514c18ec02fSPetter Reinholdtsen                return_status = OK_STATUS;
1515c18ec02fSPetter Reinholdtsen             }
1516c18ec02fSPetter Reinholdtsen          }
1517c18ec02fSPetter Reinholdtsen       }
1518c18ec02fSPetter Reinholdtsen       else{
1519c18ec02fSPetter Reinholdtsen          if (verbose == LOG_WARN){
1520c18ec02fSPetter Reinholdtsen             printf("Invalid Carrier p2p connectivity record\n");
1521c18ec02fSPetter Reinholdtsen          }
1522c18ec02fSPetter Reinholdtsen          return_status = ERROR_STATUS;
1523c18ec02fSPetter Reinholdtsen       }
1524c18ec02fSPetter Reinholdtsen       if (port_desc != NULL){
1525c18ec02fSPetter Reinholdtsen          free(port_desc);
1526c18ec02fSPetter Reinholdtsen          port_desc = NULL;
1527c18ec02fSPetter Reinholdtsen       }
1528c18ec02fSPetter Reinholdtsen    }
1529c18ec02fSPetter Reinholdtsen    return return_status;
1530c18ec02fSPetter Reinholdtsen }
1531c18ec02fSPetter Reinholdtsen 
1532c18ec02fSPetter Reinholdtsen /**************************************************************************
1533c18ec02fSPetter Reinholdtsen *
1534c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_compare_link
1535c18ec02fSPetter Reinholdtsen *
1536c18ec02fSPetter Reinholdtsen * Description: This function compares link grouping id of each
1537c18ec02fSPetter Reinholdtsen *               amc p2p connectiviy record
1538c18ec02fSPetter Reinholdtsen *
1539c18ec02fSPetter Reinholdtsen * Restriction: None
1540c18ec02fSPetter Reinholdtsen *
1541c18ec02fSPetter Reinholdtsen * Input: record1: is an AMC p2p record for an AMC module
1542c18ec02fSPetter Reinholdtsen *        record2 is an AMC p2p record for an On-Carrier record or an AMC module
1543c18ec02fSPetter Reinholdtsen *        char* opt: option string that will tell if a matching result, unmatched
1544c18ec02fSPetter Reinholdtsen *                 result or all the results will be displayed.
1545c18ec02fSPetter Reinholdtsen *        file_type1: indicates type of the first module
1546c18ec02fSPetter Reinholdtsen *        file_type2: indicates type of the second module
1547c18ec02fSPetter Reinholdtsen *
1548c18ec02fSPetter Reinholdtsen * Output: None
1549c18ec02fSPetter Reinholdtsen *
1550c18ec02fSPetter Reinholdtsen * Global: None
1551c18ec02fSPetter Reinholdtsen *
1552c18ec02fSPetter Reinholdtsen * Return:   return 0 if both link are matched, otherwise return -1
1553c18ec02fSPetter Reinholdtsen *
1554c18ec02fSPetter Reinholdtsen ***************************************************************************/
1555c18ec02fSPetter Reinholdtsen static int
ipmi_ek_compare_link(struct ipmi_ek_multi_header * physic_record,struct ipmi_ek_amc_p2p_connectivity_record record1,struct ipmi_ek_amc_p2p_connectivity_record record2,char * opt,int file_type1,int file_type2)1556c18ec02fSPetter Reinholdtsen ipmi_ek_compare_link( struct ipmi_ek_multi_header * physic_record,
1557c18ec02fSPetter Reinholdtsen    struct ipmi_ek_amc_p2p_connectivity_record record1,
1558c18ec02fSPetter Reinholdtsen    struct ipmi_ek_amc_p2p_connectivity_record record2, char * opt,
1559c18ec02fSPetter Reinholdtsen    int file_type1, int file_type2 )
1560c18ec02fSPetter Reinholdtsen {
1561c18ec02fSPetter Reinholdtsen    int result = ERROR_STATUS;
1562c18ec02fSPetter Reinholdtsen    int index1 = 0; /*index for AMC module*/
1563c18ec02fSPetter Reinholdtsen    int index2 = 0; /*index for On-carrier type*/
1564c18ec02fSPetter Reinholdtsen 
1565c18ec02fSPetter Reinholdtsen    record1.matching_result = malloc ( record1.link_desc_count * sizeof(int) );
1566c18ec02fSPetter Reinholdtsen    record2.matching_result = malloc ( record2.link_desc_count * sizeof(int) );
1567c18ec02fSPetter Reinholdtsen    /*Initialize all the matching_result to false*/
1568c18ec02fSPetter Reinholdtsen    for( index2 = 0; index2 < record2.link_desc_count; index2++ ){
1569c18ec02fSPetter Reinholdtsen       record2.matching_result[index2] = FALSE;
1570c18ec02fSPetter Reinholdtsen    }
1571c18ec02fSPetter Reinholdtsen    for( index1 = 0; index1 < record1.link_desc_count; index1++ ){
1572c18ec02fSPetter Reinholdtsen       for( index2 = 0; index2 < record2.link_desc_count; index2++ ){
1573c18ec02fSPetter Reinholdtsen          if( record1.link_desc[index1].group_id == 0 ){
1574c18ec02fSPetter Reinholdtsen             if( record2.link_desc[index2].group_id == 0 ){
1575c18ec02fSPetter Reinholdtsen                result = ipmi_ek_compare_link_descriptor(
1576c18ec02fSPetter Reinholdtsen                               record1, index1, record2, index2 );
1577c18ec02fSPetter Reinholdtsen                if ( result == OK_STATUS ){
1578c18ec02fSPetter Reinholdtsen                   /*Calculate the index for Channel descriptor in function of
1579c18ec02fSPetter Reinholdtsen                   * link designator channel ID
1580c18ec02fSPetter Reinholdtsen                   */
1581c18ec02fSPetter Reinholdtsen                   /*first channel_id in the AMC Link descriptor of record1*/
1582c18ec02fSPetter Reinholdtsen                   static int flag_first_link1;
1583c18ec02fSPetter Reinholdtsen                   int index_ch_desc1; /*index of channel descriptor */
1584c18ec02fSPetter Reinholdtsen                   /*first channel_id in the AMC Link descriptor of record2*/
1585c18ec02fSPetter Reinholdtsen                   static int flag_first_link2;
1586c18ec02fSPetter Reinholdtsen                   int index_ch_desc2; /*index of channel descriptor*/
1587c18ec02fSPetter Reinholdtsen 
1588c18ec02fSPetter Reinholdtsen                   if (index1==0){ /*this indicate the first link is encounter*/
1589c18ec02fSPetter Reinholdtsen                      flag_first_link1 = record1.link_desc[index1].channel_id;
1590c18ec02fSPetter Reinholdtsen                   }
1591c18ec02fSPetter Reinholdtsen                   index_ch_desc1 = record1.link_desc[index1].channel_id -
1592c18ec02fSPetter Reinholdtsen                               flag_first_link1;
1593c18ec02fSPetter Reinholdtsen                   if (index2==0){
1594c18ec02fSPetter Reinholdtsen                      flag_first_link2 = record2.link_desc[index2].channel_id;
1595c18ec02fSPetter Reinholdtsen                   }
1596c18ec02fSPetter Reinholdtsen                   index_ch_desc2 = record2.link_desc[index2].channel_id -
1597c18ec02fSPetter Reinholdtsen                               flag_first_link2;
1598c18ec02fSPetter Reinholdtsen                   /*Check for physical connectivity for each link*/
1599c18ec02fSPetter Reinholdtsen                   result = ipmi_ek_check_physical_connectivity ( record1,
1600c18ec02fSPetter Reinholdtsen                       index_ch_desc1, record2, index_ch_desc2,
1601c18ec02fSPetter Reinholdtsen                            physic_record, file_type1, file_type2, opt );
1602c18ec02fSPetter Reinholdtsen                   if ( result == OK_STATUS ){
1603c18ec02fSPetter Reinholdtsen                      /*Display the result if option = match or all*/
1604c18ec02fSPetter Reinholdtsen                      if ( (strcmp( opt, "match" ) == 0)
1605c18ec02fSPetter Reinholdtsen                            || (strcmp( opt, "all" ) == 0)
1606c18ec02fSPetter Reinholdtsen                            || (strcmp( opt, "default" ) == 0)
1607c18ec02fSPetter Reinholdtsen                         ){
1608c18ec02fSPetter Reinholdtsen                         tboolean isOEMtype = FALSE;
1609c18ec02fSPetter Reinholdtsen                         printf(" Matching Result\n");
1610c18ec02fSPetter Reinholdtsen                         isOEMtype = ipmi_ek_display_link_descriptor( file_type1,
1611c18ec02fSPetter Reinholdtsen                                           record2.rsc_id,
1612c18ec02fSPetter Reinholdtsen                                           "From", record2.link_desc[index2]);
1613c18ec02fSPetter Reinholdtsen                         if (isOEMtype){
1614c18ec02fSPetter Reinholdtsen                            ipmi_ek_display_oem_guid (record2);
1615c18ec02fSPetter Reinholdtsen                         }
1616c18ec02fSPetter Reinholdtsen                         isOEMtype = ipmi_ek_display_link_descriptor( file_type2,
1617c18ec02fSPetter Reinholdtsen                                           record1.rsc_id,
1618c18ec02fSPetter Reinholdtsen                                           "To", record1.link_desc[index1] );
1619c18ec02fSPetter Reinholdtsen                         if (isOEMtype){
1620c18ec02fSPetter Reinholdtsen                            ipmi_ek_display_oem_guid (record1);
1621c18ec02fSPetter Reinholdtsen                         }
1622c18ec02fSPetter Reinholdtsen                         printf("  %s\n", STAR_LINE_LIMITER);
1623c18ec02fSPetter Reinholdtsen                      }
1624c18ec02fSPetter Reinholdtsen                      record2.matching_result[index2] = TRUE;
1625c18ec02fSPetter Reinholdtsen                      record1.matching_result[index1] = TRUE;
1626c18ec02fSPetter Reinholdtsen                      /*quit the fist loop since the match is found*/
1627c18ec02fSPetter Reinholdtsen                      index2 = record2.link_desc_count;
1628c18ec02fSPetter Reinholdtsen                   }
1629c18ec02fSPetter Reinholdtsen                }
1630c18ec02fSPetter Reinholdtsen             }
1631c18ec02fSPetter Reinholdtsen          }
1632c18ec02fSPetter Reinholdtsen          else { /*Link Grouping ID is non zero, Compare all link descriptor
1633c18ec02fSPetter Reinholdtsen                  * that has non-zero link grouping id together
1634c18ec02fSPetter Reinholdtsen                  */
1635c18ec02fSPetter Reinholdtsen             if (record2.link_desc[index2].group_id != 0 ){
1636c18ec02fSPetter Reinholdtsen                result = ipmi_ek_compare_link_descriptor(
1637c18ec02fSPetter Reinholdtsen                               record1, index1, record2, index2 );
1638c18ec02fSPetter Reinholdtsen                if ( result == OK_STATUS ){
1639c18ec02fSPetter Reinholdtsen                   /*Calculate the index for Channel descriptor in function of
1640c18ec02fSPetter Reinholdtsen                   * link designator channel ID
1641c18ec02fSPetter Reinholdtsen                   */
1642c18ec02fSPetter Reinholdtsen                   /*first channel_id in the AMC Link descriptor of record1*/
1643c18ec02fSPetter Reinholdtsen                   static int flag_first_link1;
1644c18ec02fSPetter Reinholdtsen                   int index_ch_desc1; /*index of channel descriptor */
1645c18ec02fSPetter Reinholdtsen                   /*first channel_id in the AMC Link descriptor of record2*/
1646c18ec02fSPetter Reinholdtsen                   static int flag_first_link2;
1647c18ec02fSPetter Reinholdtsen                   int index_ch_desc2; /*index of channel descriptor*/
1648c18ec02fSPetter Reinholdtsen 
1649c18ec02fSPetter Reinholdtsen                   if (index1==0){ /*this indicate the first link is encounter*/
1650c18ec02fSPetter Reinholdtsen                      flag_first_link1 = record1.link_desc[index1].channel_id;
1651c18ec02fSPetter Reinholdtsen                   }
1652c18ec02fSPetter Reinholdtsen                   index_ch_desc1 = record1.link_desc[index1].channel_id -
1653c18ec02fSPetter Reinholdtsen                               flag_first_link1;
1654c18ec02fSPetter Reinholdtsen                   if (index2==0){
1655c18ec02fSPetter Reinholdtsen                      flag_first_link2 = record2.link_desc[index2].channel_id;
1656c18ec02fSPetter Reinholdtsen                   }
1657c18ec02fSPetter Reinholdtsen                   index_ch_desc2 = record2.link_desc[index2].channel_id -
1658c18ec02fSPetter Reinholdtsen                               flag_first_link2;
1659c18ec02fSPetter Reinholdtsen                   /*Check for physical connectivity for each link*/
1660c18ec02fSPetter Reinholdtsen                   result = ipmi_ek_check_physical_connectivity (
1661c18ec02fSPetter Reinholdtsen                            record1, index_ch_desc1, record2, index_ch_desc2,
1662c18ec02fSPetter Reinholdtsen                            physic_record, file_type1, file_type2, opt );
1663c18ec02fSPetter Reinholdtsen                   if ( result == OK_STATUS ){
1664c18ec02fSPetter Reinholdtsen                      if ( (strcmp( opt, "match" ) == 0)
1665c18ec02fSPetter Reinholdtsen                            || (strcmp( opt, "all" ) == 0)
1666c18ec02fSPetter Reinholdtsen                            || (strcmp( opt, "default" ) == 0)
1667c18ec02fSPetter Reinholdtsen                         ){
1668c18ec02fSPetter Reinholdtsen                         tboolean isOEMtype = FALSE;
1669c18ec02fSPetter Reinholdtsen                         printf("  Matching Result\n");
1670c18ec02fSPetter Reinholdtsen                         isOEMtype = ipmi_ek_display_link_descriptor( file_type1,
1671c18ec02fSPetter Reinholdtsen                                        record2.rsc_id,
1672c18ec02fSPetter Reinholdtsen                                        "From", record2.link_desc[index2] );
1673c18ec02fSPetter Reinholdtsen                         if ( isOEMtype ){
1674c18ec02fSPetter Reinholdtsen                            ipmi_ek_display_oem_guid (record2);
1675c18ec02fSPetter Reinholdtsen                         }
1676c18ec02fSPetter Reinholdtsen                         isOEMtype = ipmi_ek_display_link_descriptor( file_type2,
1677c18ec02fSPetter Reinholdtsen                                        record1.rsc_id,
1678c18ec02fSPetter Reinholdtsen                                        "To", record1.link_desc[index1] );
1679c18ec02fSPetter Reinholdtsen                         if (isOEMtype){
1680c18ec02fSPetter Reinholdtsen                            ipmi_ek_display_oem_guid (record1);
1681c18ec02fSPetter Reinholdtsen                         }
1682c18ec02fSPetter Reinholdtsen                         printf("  %s\n", STAR_LINE_LIMITER);
1683c18ec02fSPetter Reinholdtsen                      }
1684c18ec02fSPetter Reinholdtsen                      record2.matching_result[index2] = TRUE;
1685c18ec02fSPetter Reinholdtsen                      record1.matching_result[index1] = TRUE;
1686c18ec02fSPetter Reinholdtsen                      /*leave the fist loop since the match is found*/
1687c18ec02fSPetter Reinholdtsen                      index2 = record2.link_desc_count;
1688c18ec02fSPetter Reinholdtsen                   }
1689c18ec02fSPetter Reinholdtsen                }
1690c18ec02fSPetter Reinholdtsen             }
1691c18ec02fSPetter Reinholdtsen          }
1692c18ec02fSPetter Reinholdtsen       }
1693c18ec02fSPetter Reinholdtsen    }
1694c18ec02fSPetter Reinholdtsen 
1695c18ec02fSPetter Reinholdtsen    if ( (strcmp(opt, "unmatch") == 0) || (strcmp(opt, "all") == 0) ){
1696c18ec02fSPetter Reinholdtsen       int isOEMtype = FALSE;
1697c18ec02fSPetter Reinholdtsen       printf("  Unmatching result\n");
1698c18ec02fSPetter Reinholdtsen       for (index1 = 0; index1 < record1.link_desc_count; index1++){
1699c18ec02fSPetter Reinholdtsen          isOEMtype = ipmi_ek_display_link_descriptor( file_type2,
1700c18ec02fSPetter Reinholdtsen                            record1.rsc_id, "", record1.link_desc[index1] );
1701c18ec02fSPetter Reinholdtsen          if ( isOEMtype ){
1702c18ec02fSPetter Reinholdtsen             ipmi_ek_display_oem_guid (record1);
1703c18ec02fSPetter Reinholdtsen          }
1704c18ec02fSPetter Reinholdtsen          printf("   %s\n", STAR_LINE_LIMITER);
1705c18ec02fSPetter Reinholdtsen       }
1706c18ec02fSPetter Reinholdtsen       for ( index2 = 0; index2 < record2.link_desc_count; index2++){
1707c18ec02fSPetter Reinholdtsen          if ( !record2.matching_result[index2] ){
1708c18ec02fSPetter Reinholdtsen             isOEMtype = ipmi_ek_display_link_descriptor( file_type1,
1709c18ec02fSPetter Reinholdtsen                            record2.rsc_id, "", record2.link_desc[index2] );
1710c18ec02fSPetter Reinholdtsen             if ( isOEMtype ){
1711c18ec02fSPetter Reinholdtsen                ipmi_ek_display_oem_guid (record2);
1712c18ec02fSPetter Reinholdtsen             }
1713c18ec02fSPetter Reinholdtsen             printf("   %s\n", STAR_LINE_LIMITER);
1714c18ec02fSPetter Reinholdtsen          }
1715c18ec02fSPetter Reinholdtsen       }
1716c18ec02fSPetter Reinholdtsen    }
1717c18ec02fSPetter Reinholdtsen 
1718c18ec02fSPetter Reinholdtsen    free(record1.matching_result);
1719c18ec02fSPetter Reinholdtsen    record1.matching_result = NULL;
1720c18ec02fSPetter Reinholdtsen    free(record2.matching_result);
1721c18ec02fSPetter Reinholdtsen    record2.matching_result = NULL;
1722c18ec02fSPetter Reinholdtsen 
1723c18ec02fSPetter Reinholdtsen    return result;
1724c18ec02fSPetter Reinholdtsen }
1725c18ec02fSPetter Reinholdtsen 
1726c18ec02fSPetter Reinholdtsen /**************************************************************************
1727c18ec02fSPetter Reinholdtsen *
1728c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_compare_channel_descriptor
1729c18ec02fSPetter Reinholdtsen *
1730c18ec02fSPetter Reinholdtsen * Description: This function compares 2 channel descriptors of 2 AMC
1731c18ec02fSPetter Reinholdtsen *               point-to-point connectivity records with port descriptor of
1732c18ec02fSPetter Reinholdtsen *                carrier point-to-point connectivity record. The comparison is
1733c18ec02fSPetter Reinholdtsen *                made between each enable port only.
1734c18ec02fSPetter Reinholdtsen *
1735c18ec02fSPetter Reinholdtsen * Restriction: Reference: AMC.0 specification:
1736c18ec02fSPetter Reinholdtsen *                     - Table 3-14 for port descriptor
1737c18ec02fSPetter Reinholdtsen *                     - Table 3-17 for channel descriptor
1738c18ec02fSPetter Reinholdtsen *
1739c18ec02fSPetter Reinholdtsen * Input: ch_desc1: first channel descriptor
1740c18ec02fSPetter Reinholdtsen *        ch_desc2: second channel descriptor
1741c18ec02fSPetter Reinholdtsen *        port_desc: a pointer that contain a list of port descriptor
1742c18ec02fSPetter Reinholdtsen *        index_port: index of the port descriptor
1743c18ec02fSPetter Reinholdtsen *         rsc_id: resource id that represents as local resource id in the
1744c18ec02fSPetter Reinholdtsen *                  resource descriptor table.
1745c18ec02fSPetter Reinholdtsen *
1746c18ec02fSPetter Reinholdtsen * Output: None
1747c18ec02fSPetter Reinholdtsen *
1748c18ec02fSPetter Reinholdtsen * Global: None
1749c18ec02fSPetter Reinholdtsen *
1750c18ec02fSPetter Reinholdtsen * Return:   return TRUE if both channel descriptor are matched,
1751c18ec02fSPetter Reinholdtsen *         or FALSE otherwise
1752c18ec02fSPetter Reinholdtsen *
1753c18ec02fSPetter Reinholdtsen ***************************************************************************/
1754c18ec02fSPetter Reinholdtsen static tboolean
ipmi_ek_compare_channel_descriptor(struct fru_picmgext_amc_channel_desc_record ch_desc1,struct fru_picmgext_amc_channel_desc_record ch_desc2,struct fru_picmgext_carrier_p2p_descriptor * port_desc,int index_port,unsigned char rsc_id)1755c18ec02fSPetter Reinholdtsen ipmi_ek_compare_channel_descriptor(
1756c18ec02fSPetter Reinholdtsen       struct fru_picmgext_amc_channel_desc_record ch_desc1,
1757c18ec02fSPetter Reinholdtsen       struct fru_picmgext_amc_channel_desc_record ch_desc2,
1758c18ec02fSPetter Reinholdtsen       struct fru_picmgext_carrier_p2p_descriptor * port_desc,
1759c18ec02fSPetter Reinholdtsen       int index_port, unsigned char rsc_id )
1760c18ec02fSPetter Reinholdtsen {
1761c18ec02fSPetter Reinholdtsen    tboolean match_lane = FALSE;
1762c18ec02fSPetter Reinholdtsen 
1763c18ec02fSPetter Reinholdtsen    /* carrier p2p record start with AMC_MODULE as local port */
1764c18ec02fSPetter Reinholdtsen    if ( (rsc_id & AMC_MODULE) == AMC_MODULE ){
1765c18ec02fSPetter Reinholdtsen       if ( (ch_desc1.lane0port == port_desc[index_port].local_port)
1766c18ec02fSPetter Reinholdtsen                &&
1767c18ec02fSPetter Reinholdtsen            (ch_desc2.lane0port == port_desc[index_port].remote_port)
1768c18ec02fSPetter Reinholdtsen          ){
1769c18ec02fSPetter Reinholdtsen          /*check if the port is enable*/
1770c18ec02fSPetter Reinholdtsen          if (ch_desc1.lane1port != DISABLE_PORT){
1771c18ec02fSPetter Reinholdtsen             index_port ++;
1772c18ec02fSPetter Reinholdtsen             if ( (ch_desc1.lane1port == port_desc[index_port].local_port)
1773c18ec02fSPetter Reinholdtsen                      &&
1774c18ec02fSPetter Reinholdtsen                  (ch_desc2.lane1port == port_desc[index_port].remote_port)
1775c18ec02fSPetter Reinholdtsen                ){
1776c18ec02fSPetter Reinholdtsen                if (ch_desc1.lane2port != DISABLE_PORT){
1777c18ec02fSPetter Reinholdtsen                   index_port++;
1778c18ec02fSPetter Reinholdtsen                   if ( (ch_desc1.lane2port == port_desc[index_port].local_port)
1779c18ec02fSPetter Reinholdtsen                            &&
1780c18ec02fSPetter Reinholdtsen                        (ch_desc2.lane2port == port_desc[index_port].remote_port)
1781c18ec02fSPetter Reinholdtsen                      ){
1782c18ec02fSPetter Reinholdtsen                      if (ch_desc1.lane3port != DISABLE_PORT){
1783c18ec02fSPetter Reinholdtsen                         index_port++;
1784c18ec02fSPetter Reinholdtsen                         if ( (ch_desc1.lane3port ==
1785c18ec02fSPetter Reinholdtsen                                              port_desc[index_port].local_port)
1786c18ec02fSPetter Reinholdtsen                                  &&
1787c18ec02fSPetter Reinholdtsen                              (ch_desc2.lane3port ==
1788c18ec02fSPetter Reinholdtsen                                              port_desc[index_port].remote_port)
1789c18ec02fSPetter Reinholdtsen                            ){
1790c18ec02fSPetter Reinholdtsen                               match_lane = TRUE;
1791c18ec02fSPetter Reinholdtsen                         }
1792c18ec02fSPetter Reinholdtsen                      }
1793c18ec02fSPetter Reinholdtsen                      else{
1794c18ec02fSPetter Reinholdtsen                         match_lane = TRUE;
1795c18ec02fSPetter Reinholdtsen                      }
1796c18ec02fSPetter Reinholdtsen                   } /* end of if lane2port */
1797c18ec02fSPetter Reinholdtsen                }
1798c18ec02fSPetter Reinholdtsen                else{
1799c18ec02fSPetter Reinholdtsen                   match_lane = TRUE;
1800c18ec02fSPetter Reinholdtsen                }
1801c18ec02fSPetter Reinholdtsen             } /* end of if lane1port */
1802c18ec02fSPetter Reinholdtsen          }
1803c18ec02fSPetter Reinholdtsen          else{ /*if the port is disable, the compare result is always true*/
1804c18ec02fSPetter Reinholdtsen               match_lane = TRUE;
1805c18ec02fSPetter Reinholdtsen          }
1806c18ec02fSPetter Reinholdtsen       }/* end of if lane0port */
1807c18ec02fSPetter Reinholdtsen    }
1808c18ec02fSPetter Reinholdtsen    /* carrier p2p record start with Carrier as local port */
1809c18ec02fSPetter Reinholdtsen    else{
1810c18ec02fSPetter Reinholdtsen       if ( (ch_desc1.lane0port == port_desc[index_port].remote_port)
1811c18ec02fSPetter Reinholdtsen                &&
1812c18ec02fSPetter Reinholdtsen            (ch_desc2.lane0port == port_desc[index_port].local_port)
1813c18ec02fSPetter Reinholdtsen          ){
1814c18ec02fSPetter Reinholdtsen          if (ch_desc1.lane1port != DISABLE_PORT){
1815c18ec02fSPetter Reinholdtsen             index_port ++;
1816c18ec02fSPetter Reinholdtsen             if ( (ch_desc1.lane1port == port_desc[index_port].remote_port)
1817c18ec02fSPetter Reinholdtsen                      &&
1818c18ec02fSPetter Reinholdtsen                  (ch_desc2.lane1port == port_desc[index_port].local_port)
1819c18ec02fSPetter Reinholdtsen                ){
1820c18ec02fSPetter Reinholdtsen                if (ch_desc1.lane2port != DISABLE_PORT){
1821c18ec02fSPetter Reinholdtsen                   index_port++;
1822c18ec02fSPetter Reinholdtsen                   if ( (ch_desc1.lane2port == port_desc[index_port].remote_port)
1823c18ec02fSPetter Reinholdtsen                            &&
1824c18ec02fSPetter Reinholdtsen                        (ch_desc2.lane2port == port_desc[index_port].local_port)
1825c18ec02fSPetter Reinholdtsen                      ){
1826c18ec02fSPetter Reinholdtsen                      if (ch_desc1.lane3port != DISABLE_PORT){
1827c18ec02fSPetter Reinholdtsen                         index_port++;
1828c18ec02fSPetter Reinholdtsen                         if ( (ch_desc1.lane3port ==
1829c18ec02fSPetter Reinholdtsen                                              port_desc[index_port].remote_port)
1830c18ec02fSPetter Reinholdtsen                                  &&
1831c18ec02fSPetter Reinholdtsen                              (ch_desc2.lane3port ==
1832c18ec02fSPetter Reinholdtsen                                              port_desc[index_port].local_port)
1833c18ec02fSPetter Reinholdtsen                            ){
1834c18ec02fSPetter Reinholdtsen                               match_lane = TRUE;
1835c18ec02fSPetter Reinholdtsen                         }
1836c18ec02fSPetter Reinholdtsen                      }
1837c18ec02fSPetter Reinholdtsen                      else{
1838c18ec02fSPetter Reinholdtsen                         match_lane = TRUE;
1839c18ec02fSPetter Reinholdtsen                      }
1840c18ec02fSPetter Reinholdtsen                   } /* end of if lane2port */
1841c18ec02fSPetter Reinholdtsen                }
1842c18ec02fSPetter Reinholdtsen                else{
1843c18ec02fSPetter Reinholdtsen                   match_lane = TRUE;
1844c18ec02fSPetter Reinholdtsen                }
1845c18ec02fSPetter Reinholdtsen             } /* end of if lane1port */
1846c18ec02fSPetter Reinholdtsen          }
1847c18ec02fSPetter Reinholdtsen          else{
1848c18ec02fSPetter Reinholdtsen               match_lane = TRUE;
1849c18ec02fSPetter Reinholdtsen          }
1850c18ec02fSPetter Reinholdtsen       } /* end of if lane0port */
1851c18ec02fSPetter Reinholdtsen    }
1852c18ec02fSPetter Reinholdtsen 
1853c18ec02fSPetter Reinholdtsen    return match_lane;
1854c18ec02fSPetter Reinholdtsen }
1855c18ec02fSPetter Reinholdtsen 
1856c18ec02fSPetter Reinholdtsen /**************************************************************************
1857c18ec02fSPetter Reinholdtsen *
1858c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_compare_link_descriptor
1859c18ec02fSPetter Reinholdtsen *
1860c18ec02fSPetter Reinholdtsen * Description: This function compares 2 link descriptors of 2
1861c18ec02fSPetter Reinholdtsen *               amc p2p connectiviy record
1862c18ec02fSPetter Reinholdtsen *
1863c18ec02fSPetter Reinholdtsen * Restriction: None
1864c18ec02fSPetter Reinholdtsen *
1865c18ec02fSPetter Reinholdtsen * Input: record1: AMC p2p connectivity record of the 1rst AMC or Carrier Module
1866c18ec02fSPetter Reinholdtsen *         index1: index of AMC link descriptor in 1rst record
1867c18ec02fSPetter Reinholdtsen *         record2: AMC p2p connectivity record of the 2nd AMC or Carrier Module
1868c18ec02fSPetter Reinholdtsen *         index1: index of AMC link descriptor in 2nd record
1869c18ec02fSPetter Reinholdtsen *
1870c18ec02fSPetter Reinholdtsen * Output: None
1871c18ec02fSPetter Reinholdtsen *
1872c18ec02fSPetter Reinholdtsen * Global: None
1873c18ec02fSPetter Reinholdtsen *
1874c18ec02fSPetter Reinholdtsen * Return:   return OK_STATUS if both link are matched,
1875c18ec02fSPetter Reinholdtsen *            otherwise return ERROR_STATUS
1876c18ec02fSPetter Reinholdtsen *
1877c18ec02fSPetter Reinholdtsen ***************************************************************************/
1878c18ec02fSPetter Reinholdtsen static int
ipmi_ek_compare_link_descriptor(struct ipmi_ek_amc_p2p_connectivity_record record1,int index1,struct ipmi_ek_amc_p2p_connectivity_record record2,int index2)1879c18ec02fSPetter Reinholdtsen ipmi_ek_compare_link_descriptor(
1880b37b9149SZdenek Styblik 		struct ipmi_ek_amc_p2p_connectivity_record record1,
1881b37b9149SZdenek Styblik 		int index1,
1882b37b9149SZdenek Styblik 		struct ipmi_ek_amc_p2p_connectivity_record record2,
1883b37b9149SZdenek Styblik 		int index2)
1884c18ec02fSPetter Reinholdtsen {
1885c18ec02fSPetter Reinholdtsen 	int result = ERROR_STATUS;
1886b37b9149SZdenek Styblik 	if (record1.link_desc[index1].type != record2.link_desc[index2].type) {
1887b37b9149SZdenek Styblik 		return ERROR_STATUS;
1888b37b9149SZdenek Styblik 	}
1889c18ec02fSPetter Reinholdtsen 	/* if it is an OEM type, we compare the OEM GUID */
1890c18ec02fSPetter Reinholdtsen 	if ((record1.link_desc[index1].type >= LOWER_OEM_TYPE)
1891b37b9149SZdenek Styblik 			&& (record1.link_desc[index1].type <= UPPER_OEM_TYPE)) {
1892c18ec02fSPetter Reinholdtsen 		if ((record1.guid_count == 0) && (record2.guid_count == 0)) {
1893c18ec02fSPetter Reinholdtsen 			/*there is no GUID for comparison, so the result is always OK*/
1894c18ec02fSPetter Reinholdtsen 			result = OK_STATUS;
1895b37b9149SZdenek Styblik 		} else {
1896c18ec02fSPetter Reinholdtsen 			int i = 0;
1897c18ec02fSPetter Reinholdtsen 			int j = 0;
1898c18ec02fSPetter Reinholdtsen 			for (i = 0; i < record1.guid_count; i++) {
1899c18ec02fSPetter Reinholdtsen 				for (j = 0; j < record2.guid_count; j++) {
1900b37b9149SZdenek Styblik 					if (memcmp(&record1.oem_guid[i],
1901b37b9149SZdenek Styblik 								&record2.oem_guid[j],
1902b37b9149SZdenek Styblik 								SIZE_OF_GUID) == 0) {
1903c18ec02fSPetter Reinholdtsen 						result = OK_STATUS;
1904c18ec02fSPetter Reinholdtsen 						break;
1905c18ec02fSPetter Reinholdtsen 					}
1906c18ec02fSPetter Reinholdtsen 				}
1907c18ec02fSPetter Reinholdtsen 			}
1908c18ec02fSPetter Reinholdtsen 		}
1909b37b9149SZdenek Styblik 	} else {
1910c18ec02fSPetter Reinholdtsen 		result = OK_STATUS;
1911c18ec02fSPetter Reinholdtsen 	}
1912b37b9149SZdenek Styblik 	if (result != OK_STATUS) {
1913b37b9149SZdenek Styblik 		return result;
1914b37b9149SZdenek Styblik 	}
1915b37b9149SZdenek Styblik 	if (record1.link_desc[index1].type_ext == record2.link_desc[index2].type_ext) {
1916c18ec02fSPetter Reinholdtsen 		unsigned char asym[COMPARE_CANDIDATE];
1917c18ec02fSPetter Reinholdtsen 		int offset = 0;
1918c18ec02fSPetter Reinholdtsen 		asym[offset++] = record1.link_desc[index1].asym_match;
1919c18ec02fSPetter Reinholdtsen 		asym[offset] = record2.link_desc[index2].asym_match;
1920c18ec02fSPetter Reinholdtsen 		result = ipmi_ek_compare_asym (asym);
1921c18ec02fSPetter Reinholdtsen 		if (result == OK_STATUS){
1922c18ec02fSPetter Reinholdtsen 			struct fru_picmgext_amc_link_desc_record link[COMPARE_CANDIDATE];
1923c18ec02fSPetter Reinholdtsen 			int index = 0;
1924c18ec02fSPetter Reinholdtsen 			link[index++] = record1.link_desc[index1];
1925c18ec02fSPetter Reinholdtsen 			link[index] = record2.link_desc[index2];
1926c18ec02fSPetter Reinholdtsen 			result = ipmi_ek_compare_number_of_enable_port(link);
1927b37b9149SZdenek Styblik 		} else {
1928c18ec02fSPetter Reinholdtsen 			result = ERROR_STATUS;
1929c18ec02fSPetter Reinholdtsen 		}
1930b37b9149SZdenek Styblik 	} else {
1931c18ec02fSPetter Reinholdtsen 		result = ERROR_STATUS;
1932c18ec02fSPetter Reinholdtsen 	}
1933c18ec02fSPetter Reinholdtsen 	return result;
1934c18ec02fSPetter Reinholdtsen }
1935c18ec02fSPetter Reinholdtsen 
1936c18ec02fSPetter Reinholdtsen /**************************************************************************
1937c18ec02fSPetter Reinholdtsen *
1938c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_compare_asym
1939c18ec02fSPetter Reinholdtsen *
1940c18ec02fSPetter Reinholdtsen * Description: This function compares 2 asymetric match of 2
1941c18ec02fSPetter Reinholdtsen *               amc link descriptors
1942c18ec02fSPetter Reinholdtsen *
1943c18ec02fSPetter Reinholdtsen * Restriction: None
1944c18ec02fSPetter Reinholdtsen *
1945c18ec02fSPetter Reinholdtsen * Input:      asym[COMPARE_CANDIDATE]: Contain 2 asymetric match for comparison
1946c18ec02fSPetter Reinholdtsen *
1947c18ec02fSPetter Reinholdtsen * Output: None
1948c18ec02fSPetter Reinholdtsen *
1949c18ec02fSPetter Reinholdtsen * Global: None
1950c18ec02fSPetter Reinholdtsen *
1951c18ec02fSPetter Reinholdtsen * Return:   return 0 if both asym. match are matched, otherwise return -1
1952c18ec02fSPetter Reinholdtsen *
1953c18ec02fSPetter Reinholdtsen ***************************************************************************/
1954c18ec02fSPetter Reinholdtsen 
1955c18ec02fSPetter Reinholdtsen static int
ipmi_ek_compare_asym(unsigned char asym[COMPARE_CANDIDATE])1956c18ec02fSPetter Reinholdtsen ipmi_ek_compare_asym(unsigned char asym[COMPARE_CANDIDATE])
1957c18ec02fSPetter Reinholdtsen {
1958c18ec02fSPetter Reinholdtsen 	int return_value = ERROR_STATUS;
1959c18ec02fSPetter Reinholdtsen 	int first_index = 0;
1960c18ec02fSPetter Reinholdtsen 	int second_index = 1;
1961c18ec02fSPetter Reinholdtsen 
1962c18ec02fSPetter Reinholdtsen 	if ((asym[first_index] == 0) && (asym[second_index] == 0)) {
1963c18ec02fSPetter Reinholdtsen 		return_value = OK_STATUS;
1964b37b9149SZdenek Styblik 	} else if ((asym[first_index] & asym[second_index]) == 0) {
1965c18ec02fSPetter Reinholdtsen 		return_value = OK_STATUS;
1966b37b9149SZdenek Styblik 	} else {
1967c18ec02fSPetter Reinholdtsen 		return_value = ERROR_STATUS;
1968c18ec02fSPetter Reinholdtsen 	}
1969c18ec02fSPetter Reinholdtsen 	return return_value;
1970c18ec02fSPetter Reinholdtsen }
1971c18ec02fSPetter Reinholdtsen 
1972c18ec02fSPetter Reinholdtsen /**************************************************************************
1973c18ec02fSPetter Reinholdtsen *
1974c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_compare_link_descriptor
1975c18ec02fSPetter Reinholdtsen *
1976c18ec02fSPetter Reinholdtsen * Description: This function compare number of enble port of Link designator
1977c18ec02fSPetter Reinholdtsen *
1978c18ec02fSPetter Reinholdtsen * Restriction: None
1979c18ec02fSPetter Reinholdtsen *
1980c18ec02fSPetter Reinholdtsen * Input: link_designator1: first link designator
1981c18ec02fSPetter Reinholdtsen *        link_designator2:  second link designator
1982c18ec02fSPetter Reinholdtsen *
1983c18ec02fSPetter Reinholdtsen * Output: None
1984c18ec02fSPetter Reinholdtsen *
1985c18ec02fSPetter Reinholdtsen * Global: None
1986c18ec02fSPetter Reinholdtsen *
1987c18ec02fSPetter Reinholdtsen * Return:   return 0 if both link are matched, otherwise return -1
1988c18ec02fSPetter Reinholdtsen *
1989c18ec02fSPetter Reinholdtsen ***************************************************************************/
1990c18ec02fSPetter Reinholdtsen static int
ipmi_ek_compare_number_of_enable_port(struct fru_picmgext_amc_link_desc_record link_desc[COMPARE_CANDIDATE])1991c18ec02fSPetter Reinholdtsen ipmi_ek_compare_number_of_enable_port(
1992c18ec02fSPetter Reinholdtsen 		struct fru_picmgext_amc_link_desc_record link_desc[COMPARE_CANDIDATE])
1993c18ec02fSPetter Reinholdtsen {
1994c18ec02fSPetter Reinholdtsen 	int amc_port_count = 0;
1995c18ec02fSPetter Reinholdtsen 	int carrier_port_count = 0;
1996c18ec02fSPetter Reinholdtsen 	int return_value = ERROR_STATUS;
1997c18ec02fSPetter Reinholdtsen 	int index = 0;
1998c18ec02fSPetter Reinholdtsen 
1999b37b9149SZdenek Styblik 	if (link_desc[index].port_flag_0) {
2000b37b9149SZdenek Styblik 		/*bit 0 indicates port 0*/
2001c18ec02fSPetter Reinholdtsen 		amc_port_count++;
2002c18ec02fSPetter Reinholdtsen 	}
2003b37b9149SZdenek Styblik 	if (link_desc[index].port_flag_1) {
2004b37b9149SZdenek Styblik 		/*bit 1 indicates port 1*/
2005c18ec02fSPetter Reinholdtsen 		amc_port_count++;
2006c18ec02fSPetter Reinholdtsen 	}
2007b37b9149SZdenek Styblik 	if (link_desc[index].port_flag_2) {
2008b37b9149SZdenek Styblik 		/*bit 2 indicates port 2*/
2009c18ec02fSPetter Reinholdtsen 		amc_port_count++;
2010c18ec02fSPetter Reinholdtsen 	}
2011b37b9149SZdenek Styblik 	if (link_desc[index++].port_flag_3) {
2012b37b9149SZdenek Styblik 		/*bit 3 indicates port 3*/
2013c18ec02fSPetter Reinholdtsen 		amc_port_count++;
2014c18ec02fSPetter Reinholdtsen 	}
2015c18ec02fSPetter Reinholdtsen 
2016c18ec02fSPetter Reinholdtsen 	/* 2nd link designator */
2017b37b9149SZdenek Styblik 	if (link_desc[index].port_flag_0) {
2018b37b9149SZdenek Styblik 		/*bit 0 indicates port 0*/
2019c18ec02fSPetter Reinholdtsen 		carrier_port_count++;
2020c18ec02fSPetter Reinholdtsen 	}
2021b37b9149SZdenek Styblik 	if (link_desc[index].port_flag_1) {
2022b37b9149SZdenek Styblik 		/*bit 1 indicates port 1*/
2023c18ec02fSPetter Reinholdtsen 		carrier_port_count++;
2024c18ec02fSPetter Reinholdtsen 	}
2025b37b9149SZdenek Styblik 	if (link_desc[index].port_flag_2) {
2026b37b9149SZdenek Styblik 		/*bit 2 indicates port 2*/
2027c18ec02fSPetter Reinholdtsen 		carrier_port_count++;
2028c18ec02fSPetter Reinholdtsen 	}
2029b37b9149SZdenek Styblik 	if (link_desc[index].port_flag_3) {
2030b37b9149SZdenek Styblik 		/*bit 3 indicates port 3*/
2031c18ec02fSPetter Reinholdtsen 		carrier_port_count++;
2032c18ec02fSPetter Reinholdtsen 	}
2033c18ec02fSPetter Reinholdtsen 
2034c18ec02fSPetter Reinholdtsen 	if (carrier_port_count == amc_port_count) {
2035c18ec02fSPetter Reinholdtsen 		return_value = OK_STATUS;
2036b37b9149SZdenek Styblik 	} else {
2037c18ec02fSPetter Reinholdtsen 		return_value = ERROR_STATUS;
2038c18ec02fSPetter Reinholdtsen 	}
2039c18ec02fSPetter Reinholdtsen 	return return_value;
2040c18ec02fSPetter Reinholdtsen }
2041c18ec02fSPetter Reinholdtsen 
2042c18ec02fSPetter Reinholdtsen /**************************************************************************
2043c18ec02fSPetter Reinholdtsen *
2044c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_link_descriptor
2045c18ec02fSPetter Reinholdtsen *
2046c18ec02fSPetter Reinholdtsen * Description: Display the link descriptor of an AMC p2p connectivity record
2047c18ec02fSPetter Reinholdtsen *
2048c18ec02fSPetter Reinholdtsen * Restriction: See AMC.0 or PICMG 3.0 specification for detail about bit masks
2049c18ec02fSPetter Reinholdtsen *
2050c18ec02fSPetter Reinholdtsen * Input: file_type: module type.
2051c18ec02fSPetter Reinholdtsen *        rsc_id: resource id
2052c18ec02fSPetter Reinholdtsen *        char* str: indicates if it is a source (its value= "From") or a
2053c18ec02fSPetter Reinholdtsen *                 destination (its value = "To"). ( it is set to "" if it is not
2054c18ec02fSPetter Reinholdtsen *                 a source nor destination
2055c18ec02fSPetter Reinholdtsen *        link_desc: AMC link descriptor
2056c18ec02fSPetter Reinholdtsen *        asym:  asymetric match
2057c18ec02fSPetter Reinholdtsen *
2058c18ec02fSPetter Reinholdtsen * Output: None
2059c18ec02fSPetter Reinholdtsen *
2060c18ec02fSPetter Reinholdtsen * Global: None
2061c18ec02fSPetter Reinholdtsen *
2062c18ec02fSPetter Reinholdtsen * Return: None
2063c18ec02fSPetter Reinholdtsen *
2064c18ec02fSPetter Reinholdtsen ***************************************************************************/
2065c18ec02fSPetter Reinholdtsen static tboolean
ipmi_ek_display_link_descriptor(int file_type,unsigned char rsc_id,char * str,struct fru_picmgext_amc_link_desc_record link_desc)2066c18ec02fSPetter Reinholdtsen ipmi_ek_display_link_descriptor(int file_type, unsigned char rsc_id,
2067b37b9149SZdenek Styblik 		char *str,
2068b37b9149SZdenek Styblik 		struct fru_picmgext_amc_link_desc_record link_desc)
2069c18ec02fSPetter Reinholdtsen {
2070c18ec02fSPetter Reinholdtsen 	tboolean isOEMtype = FALSE;
2071c18ec02fSPetter Reinholdtsen 	if (file_type == ON_CARRIER_FRU_FILE) {
2072b37b9149SZdenek Styblik 		printf("  - %s On-Carrier Device ID %d\n", str,
2073b37b9149SZdenek Styblik 				(rsc_id & 0x0f));
2074b37b9149SZdenek Styblik 	} else {
2075b37b9149SZdenek Styblik 		printf("  - %s %s\n", str, val2str(file_type,
2076b37b9149SZdenek Styblik 					ipmi_ekanalyzer_module_type));
2077c18ec02fSPetter Reinholdtsen 	}
2078c18ec02fSPetter Reinholdtsen 	printf("    - Channel ID %d || ",  link_desc.channel_id);
2079c18ec02fSPetter Reinholdtsen 	printf("%s", link_desc.port_flag_0 ? "Lane 0: enable" : "");
2080c18ec02fSPetter Reinholdtsen 	printf("%s", link_desc.port_flag_1 ? ", Lane 1: enable" : "");
2081c18ec02fSPetter Reinholdtsen 	printf("%s", link_desc.port_flag_2 ? ", Lane 2: enable" : "");
2082c18ec02fSPetter Reinholdtsen 	printf("%s", link_desc.port_flag_3 ? ", Lane 3: enable" : "");
2083c18ec02fSPetter Reinholdtsen 	printf("\n");
2084b37b9149SZdenek Styblik 	printf("    - Link Type: %s \n", val2str(link_desc.type,
2085b37b9149SZdenek Styblik 				ipmi_ekanalyzer_link_type));
2086c18ec02fSPetter Reinholdtsen 	switch (link_desc.type) {
2087c18ec02fSPetter Reinholdtsen 	case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE:
2088c18ec02fSPetter Reinholdtsen 	case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS1:
2089c18ec02fSPetter Reinholdtsen 	case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS2:
2090c18ec02fSPetter Reinholdtsen 		printf("    - Link Type extension: %s\n",
2091b37b9149SZdenek Styblik 				val2str(link_desc.type_ext,
2092b37b9149SZdenek Styblik 					ipmi_ekanalyzer_extension_PCIE));
2093c18ec02fSPetter Reinholdtsen 		printf("    - Link Group ID: %d || ", link_desc.group_id);
2094c18ec02fSPetter Reinholdtsen 		printf("Link Asym. Match: %d - %s\n",
2095c18ec02fSPetter Reinholdtsen 				link_desc.asym_match,
2096b37b9149SZdenek Styblik 				val2str(link_desc.asym_match,
2097b37b9149SZdenek Styblik 					ipmi_ekanalyzer_asym_PCIE));
2098c18ec02fSPetter Reinholdtsen 		break;
2099c18ec02fSPetter Reinholdtsen 	case FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET:
2100c18ec02fSPetter Reinholdtsen 		printf("    - Link Type extension: %s\n",
2101b37b9149SZdenek Styblik 				val2str(link_desc.type_ext,
2102b37b9149SZdenek Styblik 					ipmi_ekanalyzer_extension_ETHERNET));
2103c18ec02fSPetter Reinholdtsen 		printf("    - Link Group ID: %d || ", link_desc.group_id);
2104c18ec02fSPetter Reinholdtsen 		printf("Link Asym. Match: %d - %s\n",
2105c18ec02fSPetter Reinholdtsen 				link_desc.asym_match,
2106b37b9149SZdenek Styblik 				val2str(link_desc.asym_match,
2107b37b9149SZdenek Styblik 					ipmi_ekanalyzer_asym_PCIE));
2108c18ec02fSPetter Reinholdtsen 		break;
2109c18ec02fSPetter Reinholdtsen 	case FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE:
2110c18ec02fSPetter Reinholdtsen 		printf("    - Link Type extension: %s\n",
2111b37b9149SZdenek Styblik 				val2str(link_desc.type_ext,
2112b37b9149SZdenek Styblik 					ipmi_ekanalyzer_extension_STORAGE));
2113b37b9149SZdenek Styblik 		printf("    - Link Group ID: %d || ",
2114b37b9149SZdenek Styblik 				link_desc.group_id);
2115c18ec02fSPetter Reinholdtsen 		printf("Link Asym. Match: %d - %s\n",
2116c18ec02fSPetter Reinholdtsen 				link_desc.asym_match,
2117b37b9149SZdenek Styblik 				val2str(link_desc.asym_match,
2118b37b9149SZdenek Styblik 					ipmi_ekanalyzer_asym_STORAGE));
2119c18ec02fSPetter Reinholdtsen 		break;
2120c18ec02fSPetter Reinholdtsen 	default:
2121b37b9149SZdenek Styblik 		printf("    - Link Type extension: %i\n",
2122b37b9149SZdenek Styblik 				link_desc.type_ext);
2123b37b9149SZdenek Styblik 		printf("    - Link Group ID: %d || ",
2124b37b9149SZdenek Styblik 				link_desc.group_id);
2125b37b9149SZdenek Styblik 		printf("Link Asym. Match: %i\n",
2126b37b9149SZdenek Styblik 				link_desc.asym_match);
2127c18ec02fSPetter Reinholdtsen 		break;
2128c18ec02fSPetter Reinholdtsen 	}
2129c18ec02fSPetter Reinholdtsen 	/* return as OEM type if link type indicates OEM */
2130c18ec02fSPetter Reinholdtsen 	if ((link_desc.type >= LOWER_OEM_TYPE)
2131b37b9149SZdenek Styblik 			&& (link_desc.type <= UPPER_OEM_TYPE)) {
2132c18ec02fSPetter Reinholdtsen 		isOEMtype = TRUE;
2133c18ec02fSPetter Reinholdtsen 	}
2134c18ec02fSPetter Reinholdtsen 	return isOEMtype;
2135c18ec02fSPetter Reinholdtsen }
2136c18ec02fSPetter Reinholdtsen 
2137c18ec02fSPetter Reinholdtsen /**************************************************************************
2138c18ec02fSPetter Reinholdtsen *
2139c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_oem_guid
2140c18ec02fSPetter Reinholdtsen *
2141c18ec02fSPetter Reinholdtsen * Description: Display the oem guid of an AMC p2p connectivity record
2142c18ec02fSPetter Reinholdtsen *
2143c18ec02fSPetter Reinholdtsen * Restriction: None
2144c18ec02fSPetter Reinholdtsen *
2145c18ec02fSPetter Reinholdtsen * Input: amc_record: AMC p2p connectivity record
2146c18ec02fSPetter Reinholdtsen *
2147c18ec02fSPetter Reinholdtsen * Output: None
2148c18ec02fSPetter Reinholdtsen *
2149c18ec02fSPetter Reinholdtsen * Global: None
2150c18ec02fSPetter Reinholdtsen *
2151c18ec02fSPetter Reinholdtsen * Return: None
2152c18ec02fSPetter Reinholdtsen *
2153c18ec02fSPetter Reinholdtsen ***************************************************************************/
2154c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_oem_guid(struct ipmi_ek_amc_p2p_connectivity_record amc_record)2155b37b9149SZdenek Styblik ipmi_ek_display_oem_guid(struct ipmi_ek_amc_p2p_connectivity_record amc_record)
2156c18ec02fSPetter Reinholdtsen {
2157c18ec02fSPetter Reinholdtsen 	int index_oem = 0;
2158c18ec02fSPetter Reinholdtsen 	int index = 0;
2159c18ec02fSPetter Reinholdtsen 	if (amc_record.guid_count == 0) {
2160c18ec02fSPetter Reinholdtsen 		printf("\tThere is no OEM GUID for this module\n");
2161c18ec02fSPetter Reinholdtsen 	}
2162c18ec02fSPetter Reinholdtsen 	for (index_oem = 0; index_oem < amc_record.guid_count; index_oem++) {
2163c18ec02fSPetter Reinholdtsen 		printf("    - GUID: ");
2164c18ec02fSPetter Reinholdtsen 		for (index = 0; index < SIZE_OF_GUID; index++) {
2165b37b9149SZdenek Styblik 			printf("%02x",
2166b37b9149SZdenek Styblik 					amc_record.oem_guid[index_oem].guid[index]);
2167b37b9149SZdenek Styblik 			/* For a better look: putting a "-" after displaying
2168b37b9149SZdenek Styblik 			 * four bytes of GUID
2169b37b9149SZdenek Styblik 			 */
2170c18ec02fSPetter Reinholdtsen 			if (!(index % 4)){
2171c18ec02fSPetter Reinholdtsen 				printf("-");
2172c18ec02fSPetter Reinholdtsen 			}
2173c18ec02fSPetter Reinholdtsen 		}
2174c18ec02fSPetter Reinholdtsen 		printf("\n");
2175c18ec02fSPetter Reinholdtsen 	}
2176c18ec02fSPetter Reinholdtsen }
2177c18ec02fSPetter Reinholdtsen 
2178c18ec02fSPetter Reinholdtsen /**************************************************************************
2179c18ec02fSPetter Reinholdtsen *
2180c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_create_amc_p2p_record
2181c18ec02fSPetter Reinholdtsen *
2182c18ec02fSPetter Reinholdtsen * Description: this function create an AMC point 2 point connectivity record
2183c18ec02fSPetter Reinholdtsen *            that contain link descriptor, channel descriptor, oem guid
2184c18ec02fSPetter Reinholdtsen *
2185c18ec02fSPetter Reinholdtsen * Restriction: Reference: AMC.0 Specification Table 3-16
2186c18ec02fSPetter Reinholdtsen *
2187c18ec02fSPetter Reinholdtsen * Input: record: a pointer to FRU multi record
2188c18ec02fSPetter Reinholdtsen *
2189c18ec02fSPetter Reinholdtsen * Output: amc_record: a pointer to the created AMC p2p record
2190c18ec02fSPetter Reinholdtsen *
2191c18ec02fSPetter Reinholdtsen * Global: None
2192c18ec02fSPetter Reinholdtsen *
2193c18ec02fSPetter Reinholdtsen * Return: Return OK_STATUS on success, or ERROR_STATUS if no record has been
2194c18ec02fSPetter Reinholdtsen *          created.
2195c18ec02fSPetter Reinholdtsen *
2196c18ec02fSPetter Reinholdtsen ***************************************************************************/
2197c18ec02fSPetter Reinholdtsen static int
ipmi_ek_create_amc_p2p_record(struct ipmi_ek_multi_header * record,struct ipmi_ek_amc_p2p_connectivity_record * amc_record)2198c18ec02fSPetter Reinholdtsen ipmi_ek_create_amc_p2p_record(struct ipmi_ek_multi_header *record,
2199c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_amc_p2p_connectivity_record *amc_record)
2200c18ec02fSPetter Reinholdtsen {
2201c18ec02fSPetter Reinholdtsen 	int index_data = START_DATA_OFFSET;
2202c18ec02fSPetter Reinholdtsen 	int return_status = OK_STATUS;
2203c18ec02fSPetter Reinholdtsen 
2204c18ec02fSPetter Reinholdtsen 	amc_record->guid_count = record->data[index_data++];
2205c18ec02fSPetter Reinholdtsen 	if (amc_record->guid_count > 0) {
2206c18ec02fSPetter Reinholdtsen 		int index_oem = 0;
2207c18ec02fSPetter Reinholdtsen 		amc_record->oem_guid = malloc(amc_record->guid_count * \
2208c18ec02fSPetter Reinholdtsen 				sizeof(struct fru_picmgext_guid));
2209c18ec02fSPetter Reinholdtsen 		for (index_oem = 0; index_oem < amc_record->guid_count;
2210c18ec02fSPetter Reinholdtsen 				index_oem++) {
2211c18ec02fSPetter Reinholdtsen 			memcpy(&amc_record->oem_guid[index_oem].guid,
2212c18ec02fSPetter Reinholdtsen 					&record->data[index_data],
2213c18ec02fSPetter Reinholdtsen 					SIZE_OF_GUID);
2214c18ec02fSPetter Reinholdtsen 			index_data += (int)SIZE_OF_GUID;
2215c18ec02fSPetter Reinholdtsen 		}
2216c18ec02fSPetter Reinholdtsen 		amc_record->rsc_id = record->data[index_data++];
2217c18ec02fSPetter Reinholdtsen 		amc_record->ch_count = record->data[index_data++];
2218c18ec02fSPetter Reinholdtsen 		/* Calculate link descriptor count */
2219c18ec02fSPetter Reinholdtsen 		amc_record->link_desc_count = ((record->header.len) - 8 -
2220c18ec02fSPetter Reinholdtsen 				(SIZE_OF_GUID*amc_record->guid_count) -
2221c18ec02fSPetter Reinholdtsen 				(FRU_PICMGEXT_AMC_CHANNEL_DESC_RECORD_SIZE *
2222c18ec02fSPetter Reinholdtsen 				amc_record->ch_count)) / 5 ;
2223c18ec02fSPetter Reinholdtsen 	} else {
2224c18ec02fSPetter Reinholdtsen 		amc_record->rsc_id = record->data[index_data++];
2225c18ec02fSPetter Reinholdtsen 		amc_record->ch_count = record->data[index_data++];
2226c18ec02fSPetter Reinholdtsen 		/* Calculate link descriptor count see spec AMC.0 for detail */
2227c18ec02fSPetter Reinholdtsen 		amc_record->link_desc_count = ((record->header.len) - 8 -
2228c18ec02fSPetter Reinholdtsen 				(FRU_PICMGEXT_AMC_CHANNEL_DESC_RECORD_SIZE *
2229c18ec02fSPetter Reinholdtsen 				amc_record->ch_count)) / 5;
2230c18ec02fSPetter Reinholdtsen 	}
2231c18ec02fSPetter Reinholdtsen 
2232c18ec02fSPetter Reinholdtsen 	if (amc_record->ch_count > 0) {
2233c18ec02fSPetter Reinholdtsen 		int ch_index = 0;
2234c18ec02fSPetter Reinholdtsen 		amc_record->ch_desc = malloc((amc_record->ch_count) * \
2235c18ec02fSPetter Reinholdtsen 				sizeof(struct fru_picmgext_amc_channel_desc_record));
2236c18ec02fSPetter Reinholdtsen 		for (ch_index = 0; ch_index < amc_record->ch_count;
2237c18ec02fSPetter Reinholdtsen 				ch_index++) {
2238c18ec02fSPetter Reinholdtsen 			unsigned int data;
2239c18ec02fSPetter Reinholdtsen 			struct fru_picmgext_amc_channel_desc_record *src, *dst;
2240c18ec02fSPetter Reinholdtsen 			data = record->data[index_data] |
2241c18ec02fSPetter Reinholdtsen 				(record->data[index_data + 1] << 8) |
2242c18ec02fSPetter Reinholdtsen 				(record->data[index_data + 2] << 16);
2243c18ec02fSPetter Reinholdtsen 
2244c18ec02fSPetter Reinholdtsen 			src = (struct fru_picmgext_amc_channel_desc_record *)&data;
2245c18ec02fSPetter Reinholdtsen 			dst = (struct fru_picmgext_amc_channel_desc_record *)
2246c18ec02fSPetter Reinholdtsen 				&amc_record->ch_desc[ch_index];
2247c18ec02fSPetter Reinholdtsen 
2248c18ec02fSPetter Reinholdtsen 			dst->lane0port = src->lane0port;
2249c18ec02fSPetter Reinholdtsen 			dst->lane1port = src->lane1port;
2250c18ec02fSPetter Reinholdtsen 			dst->lane2port = src->lane2port;
2251c18ec02fSPetter Reinholdtsen 			dst->lane3port = src->lane3port;
2252c18ec02fSPetter Reinholdtsen 			index_data += FRU_PICMGEXT_AMC_CHANNEL_DESC_RECORD_SIZE;
2253c18ec02fSPetter Reinholdtsen 		}
2254c18ec02fSPetter Reinholdtsen 	}
2255c18ec02fSPetter Reinholdtsen 	if (amc_record->link_desc_count > 0) {
2256c18ec02fSPetter Reinholdtsen 		int i=0;
2257c18ec02fSPetter Reinholdtsen 		amc_record->link_desc = malloc(amc_record->link_desc_count * \
2258c18ec02fSPetter Reinholdtsen 				sizeof(struct fru_picmgext_amc_link_desc_record));
2259c18ec02fSPetter Reinholdtsen 		for (i = 0; i< amc_record->link_desc_count; i++) {
2260c18ec02fSPetter Reinholdtsen 			unsigned int data[2];
2261c18ec02fSPetter Reinholdtsen 			struct fru_picmgext_amc_link_desc_record *src, *dst;
2262c18ec02fSPetter Reinholdtsen 			data[0] = record->data[index_data] |
2263c18ec02fSPetter Reinholdtsen 				(record->data[index_data + 1] << 8) |
2264c18ec02fSPetter Reinholdtsen 				(record->data[index_data + 2] << 16) |
2265c18ec02fSPetter Reinholdtsen 				(record->data[index_data + 3] << 24);
2266c18ec02fSPetter Reinholdtsen 
2267c18ec02fSPetter Reinholdtsen 			data[1] = record->data[index_data + 4];
2268c18ec02fSPetter Reinholdtsen 			src = (struct fru_picmgext_amc_link_desc_record*)&data;
2269c18ec02fSPetter Reinholdtsen 			dst = (struct fru_picmgext_amc_link_desc_record*)
2270c18ec02fSPetter Reinholdtsen 				&amc_record->link_desc[i];
2271c18ec02fSPetter Reinholdtsen 
2272c18ec02fSPetter Reinholdtsen 			dst->channel_id = src->channel_id;
2273c18ec02fSPetter Reinholdtsen 			dst->port_flag_0 = src->port_flag_0;
2274c18ec02fSPetter Reinholdtsen 			dst->port_flag_1 = src->port_flag_1;
2275c18ec02fSPetter Reinholdtsen 			dst->port_flag_2 = src->port_flag_2;
2276c18ec02fSPetter Reinholdtsen 			dst->port_flag_3 = src->port_flag_3;
2277c18ec02fSPetter Reinholdtsen 			dst->type = src->type;
2278c18ec02fSPetter Reinholdtsen 			dst->type_ext = src->type_ext;
2279c18ec02fSPetter Reinholdtsen 			dst->group_id = src->group_id;
2280c18ec02fSPetter Reinholdtsen 			dst->asym_match = src->asym_match;
2281c18ec02fSPetter Reinholdtsen 			index_data += FRU_PICMGEXT_AMC_LINK_DESC_RECORD_SIZE;
2282c18ec02fSPetter Reinholdtsen 		}
2283c18ec02fSPetter Reinholdtsen 	} else {
2284c18ec02fSPetter Reinholdtsen 		return_status = ERROR_STATUS;
2285c18ec02fSPetter Reinholdtsen 	}
2286c18ec02fSPetter Reinholdtsen 	return return_status;
2287c18ec02fSPetter Reinholdtsen }
2288c18ec02fSPetter Reinholdtsen 
2289c18ec02fSPetter Reinholdtsen /**************************************************************************
2290c18ec02fSPetter Reinholdtsen *
2291c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_get_resource_descriptor
2292c18ec02fSPetter Reinholdtsen *
2293c18ec02fSPetter Reinholdtsen * Description: this function create the resource descriptor of Carrier p2p
2294c18ec02fSPetter Reinholdtsen *              connectivity record.
2295c18ec02fSPetter Reinholdtsen *
2296c18ec02fSPetter Reinholdtsen * Restriction: None
2297c18ec02fSPetter Reinholdtsen *
2298c18ec02fSPetter Reinholdtsen * Input: port_count: number of port count
2299c18ec02fSPetter Reinholdtsen *        index: index to the position of data start offset
2300c18ec02fSPetter Reinholdtsen *        record: a pointer to FRU multi record
2301c18ec02fSPetter Reinholdtsen *
2302c18ec02fSPetter Reinholdtsen * Output: port_desc: a pointer to the created resource descriptor
2303c18ec02fSPetter Reinholdtsen *
2304c18ec02fSPetter Reinholdtsen * Global: None
2305c18ec02fSPetter Reinholdtsen *
2306c18ec02fSPetter Reinholdtsen * Return: Return index that indicates the current position of data in record.
2307c18ec02fSPetter Reinholdtsen *
2308c18ec02fSPetter Reinholdtsen ***************************************************************************/
2309c18ec02fSPetter Reinholdtsen static int
ipmi_ek_get_resource_descriptor(int port_count,int index,struct fru_picmgext_carrier_p2p_descriptor * port_desc,struct ipmi_ek_multi_header * record)2310c18ec02fSPetter Reinholdtsen ipmi_ek_get_resource_descriptor(int port_count, int index,
2311c18ec02fSPetter Reinholdtsen 		struct fru_picmgext_carrier_p2p_descriptor *port_desc,
2312c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header *record)
2313c18ec02fSPetter Reinholdtsen {
2314c18ec02fSPetter Reinholdtsen 	int num_port = 0;
2315c18ec02fSPetter Reinholdtsen 	while (num_port < port_count) {
2316c18ec02fSPetter Reinholdtsen 		memcpy(&port_desc[num_port], &record->data[index],
2317c18ec02fSPetter Reinholdtsen 				sizeof (struct fru_picmgext_carrier_p2p_descriptor));
2318c18ec02fSPetter Reinholdtsen 		index += sizeof (struct fru_picmgext_carrier_p2p_descriptor);
2319c18ec02fSPetter Reinholdtsen 		num_port++;
2320c18ec02fSPetter Reinholdtsen 	}
2321c18ec02fSPetter Reinholdtsen 	return index;
2322c18ec02fSPetter Reinholdtsen }
2323c18ec02fSPetter Reinholdtsen 
2324c18ec02fSPetter Reinholdtsen /**************************************************************************
2325c18ec02fSPetter Reinholdtsen *
2326c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_fru_header
2327c18ec02fSPetter Reinholdtsen *
2328c18ec02fSPetter Reinholdtsen * Description: this function display FRU header offset from a FRU binary file
2329c18ec02fSPetter Reinholdtsen *
2330c18ec02fSPetter Reinholdtsen * Restriction: Reference: IPMI Platform Management FRU Information Storage
2331c18ec02fSPetter Reinholdtsen *                  Definition V1.0, Section 8
2332c18ec02fSPetter Reinholdtsen *
2333c18ec02fSPetter Reinholdtsen * Input: filename: name of FRU binary file
2334c18ec02fSPetter Reinholdtsen *
2335c18ec02fSPetter Reinholdtsen * Output: None
2336c18ec02fSPetter Reinholdtsen *
2337c18ec02fSPetter Reinholdtsen * Global: None
2338c18ec02fSPetter Reinholdtsen *
2339c18ec02fSPetter Reinholdtsen * Return: Return OK_STATUS on sucess, ERROR_STATUS on error
2340c18ec02fSPetter Reinholdtsen *
2341c18ec02fSPetter Reinholdtsen ***************************************************************************/
2342c18ec02fSPetter Reinholdtsen static int
ipmi_ek_display_fru_header(char * filename)2343c18ec02fSPetter Reinholdtsen ipmi_ek_display_fru_header(char *filename)
2344c18ec02fSPetter Reinholdtsen {
2345c18ec02fSPetter Reinholdtsen 	FILE *input_file;
2346c18ec02fSPetter Reinholdtsen 	struct fru_header header;
2347c18ec02fSPetter Reinholdtsen 	int ret = 0;
2348c18ec02fSPetter Reinholdtsen 
2349c18ec02fSPetter Reinholdtsen 	input_file = fopen(filename, "r");
2350c18ec02fSPetter Reinholdtsen 	if (input_file == NULL) {
2351c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "File '%s' not found.", filename);
2352c18ec02fSPetter Reinholdtsen 		return (ERROR_STATUS);
2353c18ec02fSPetter Reinholdtsen 	}
2354c18ec02fSPetter Reinholdtsen 	ret = fread(&header, sizeof (struct fru_header), 1, input_file);
2355c18ec02fSPetter Reinholdtsen 	if ((ret != 1) || ferror(input_file)) {
2356c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Failed to read FRU header!");
2357c18ec02fSPetter Reinholdtsen 		fclose(input_file);
2358c18ec02fSPetter Reinholdtsen 		return (ERROR_STATUS);
2359c18ec02fSPetter Reinholdtsen 	}
2360c18ec02fSPetter Reinholdtsen 	printf("%s\n", EQUAL_LINE_LIMITER);
2361c18ec02fSPetter Reinholdtsen 	printf("FRU Header Info\n");
2362c18ec02fSPetter Reinholdtsen 	printf("%s\n", EQUAL_LINE_LIMITER);
2363c18ec02fSPetter Reinholdtsen 	printf("Format Version          :0x%02x %s\n",
2364c18ec02fSPetter Reinholdtsen 		(header.version & 0x0f),
2365c18ec02fSPetter Reinholdtsen 		((header.version & 0x0f) == 1) ? "" : "{unsupported}");
2366c18ec02fSPetter Reinholdtsen 	printf("Internal Use Offset     :0x%02x\n", header.offset.internal);
2367c18ec02fSPetter Reinholdtsen 	printf("Chassis Info Offset     :0x%02x\n", header.offset.chassis);
2368c18ec02fSPetter Reinholdtsen 	printf("Board Info Offset       :0x%02x\n", header.offset.board);
2369c18ec02fSPetter Reinholdtsen 	printf("Product Info Offset     :0x%02x\n", header.offset.product);
2370c18ec02fSPetter Reinholdtsen 	printf("MultiRecord Offset      :0x%02x\n", header.offset.multi);
2371c18ec02fSPetter Reinholdtsen 	printf("Common header Checksum  :0x%02x\n", header.checksum);
2372c18ec02fSPetter Reinholdtsen 
2373c18ec02fSPetter Reinholdtsen 	fclose(input_file);
2374c18ec02fSPetter Reinholdtsen 	return OK_STATUS;
2375c18ec02fSPetter Reinholdtsen }
2376c18ec02fSPetter Reinholdtsen 
2377c18ec02fSPetter Reinholdtsen /**************************************************************************
2378c18ec02fSPetter Reinholdtsen *
2379c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_fru_header_detail
2380c18ec02fSPetter Reinholdtsen *
2381c18ec02fSPetter Reinholdtsen * Description: this function display detail FRU header information
2382c18ec02fSPetter Reinholdtsen *               from a FRU binary file.
2383c18ec02fSPetter Reinholdtsen 
2384c18ec02fSPetter Reinholdtsen *
2385c18ec02fSPetter Reinholdtsen * Restriction: Reference: IPMI Platform Management FRU Information Storage
2386c18ec02fSPetter Reinholdtsen *                  Definition V1.0, Section 8
2387c18ec02fSPetter Reinholdtsen *
2388c18ec02fSPetter Reinholdtsen * Input: filename: name of FRU binary file
2389c18ec02fSPetter Reinholdtsen *
2390c18ec02fSPetter Reinholdtsen * Output: None
2391c18ec02fSPetter Reinholdtsen *
2392c18ec02fSPetter Reinholdtsen * Global: None
2393c18ec02fSPetter Reinholdtsen *
2394c18ec02fSPetter Reinholdtsen * Return: None
2395c18ec02fSPetter Reinholdtsen *
2396c18ec02fSPetter Reinholdtsen ***************************************************************************/
2397c18ec02fSPetter Reinholdtsen static int
ipmi_ek_display_fru_header_detail(char * filename)2398c18ec02fSPetter Reinholdtsen ipmi_ek_display_fru_header_detail(char *filename)
2399c18ec02fSPetter Reinholdtsen {
2400c18ec02fSPetter Reinholdtsen # define FACTOR_OFFSET 8
2401c18ec02fSPetter Reinholdtsen # define SIZE_MFG_DATE 3
2402c18ec02fSPetter Reinholdtsen 	FILE *input_file;
2403c18ec02fSPetter Reinholdtsen 	size_t file_offset = 0;
2404c18ec02fSPetter Reinholdtsen 	struct fru_header header;
2405c18ec02fSPetter Reinholdtsen 	time_t tval;
2406c18ec02fSPetter Reinholdtsen 	int ret = 0;
2407c18ec02fSPetter Reinholdtsen 	unsigned char data = 0;
2408c18ec02fSPetter Reinholdtsen 	unsigned char lan_code = 0;
2409c18ec02fSPetter Reinholdtsen 	unsigned char mfg_date[SIZE_MFG_DATE];
2410c18ec02fSPetter Reinholdtsen 	unsigned int board_length = 0;
2411c18ec02fSPetter Reinholdtsen 
2412c18ec02fSPetter Reinholdtsen 	input_file = fopen(filename, "r");
2413c18ec02fSPetter Reinholdtsen 	if (input_file == NULL) {
2414c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "File '%s' not found.", filename);
2415c18ec02fSPetter Reinholdtsen 		return (-1);
2416c18ec02fSPetter Reinholdtsen 	}
2417c18ec02fSPetter Reinholdtsen 	/* The offset in each fru is in multiple of 8 bytes
2418c18ec02fSPetter Reinholdtsen 	 * See IPMI Platform Management FRU Information Storage Definition
2419c18ec02fSPetter Reinholdtsen 	 * for detail
2420c18ec02fSPetter Reinholdtsen 	 */
2421c18ec02fSPetter Reinholdtsen 	ret = fread(&header, sizeof(struct fru_header), 1, input_file);
2422c18ec02fSPetter Reinholdtsen 	if ((ret != 1) || ferror(input_file)) {
2423c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Failed to read FRU header!");
2424c18ec02fSPetter Reinholdtsen 		fclose(input_file);
2425c18ec02fSPetter Reinholdtsen 		return (-1);
2426c18ec02fSPetter Reinholdtsen 	}
2427c18ec02fSPetter Reinholdtsen 	/*** Display FRU Internal Use Info ***/
2428c18ec02fSPetter Reinholdtsen 	if (!feof(input_file)) {
2429c18ec02fSPetter Reinholdtsen 		unsigned char format_version;
2430c18ec02fSPetter Reinholdtsen 		unsigned long len = 0;
2431c18ec02fSPetter Reinholdtsen 
2432c18ec02fSPetter Reinholdtsen 		printf("%s\n", EQUAL_LINE_LIMITER);
2433c18ec02fSPetter Reinholdtsen 		printf("FRU Internal Use Info\n");
2434c18ec02fSPetter Reinholdtsen 		printf("%s\n", EQUAL_LINE_LIMITER);
2435c18ec02fSPetter Reinholdtsen 
2436c18ec02fSPetter Reinholdtsen 		ret = fread(&format_version, 1, 1, input_file);
2437c18ec02fSPetter Reinholdtsen 		if ((ret != 1) || ferror(input_file)) {
2438c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid format version!");
2439c18ec02fSPetter Reinholdtsen 			fclose(input_file);
2440c18ec02fSPetter Reinholdtsen 			return (-1);
2441c18ec02fSPetter Reinholdtsen 		}
2442c18ec02fSPetter Reinholdtsen 		printf("Format Version: %d\n", (format_version & 0x0f));
2443c18ec02fSPetter Reinholdtsen 
2444c18ec02fSPetter Reinholdtsen 		if (header.offset.chassis > 0) {
2445c18ec02fSPetter Reinholdtsen 			len = (header.offset.chassis * FACTOR_OFFSET)
2446c18ec02fSPetter Reinholdtsen 				- (header.offset.internal * FACTOR_OFFSET);
2447c18ec02fSPetter Reinholdtsen 		} else {
2448c18ec02fSPetter Reinholdtsen 			len = (header.offset.board * FACTOR_OFFSET)
2449c18ec02fSPetter Reinholdtsen 				- (header.offset.internal * FACTOR_OFFSET);
2450c18ec02fSPetter Reinholdtsen 		}
2451c18ec02fSPetter Reinholdtsen 		printf("Length: %ld\n", len);
2452c18ec02fSPetter Reinholdtsen 		printf("Data dump:\n");
2453c18ec02fSPetter Reinholdtsen 		while ((len > 0) && (!feof(input_file))) {
2454c18ec02fSPetter Reinholdtsen 			unsigned char data;
2455c18ec02fSPetter Reinholdtsen 			ret = fread(&data, 1, 1, input_file);
2456c18ec02fSPetter Reinholdtsen 			if ((ret != 1) || ferror(input_file)) {
2457c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Invalid data!");
2458c18ec02fSPetter Reinholdtsen 				fclose(input_file);
2459c18ec02fSPetter Reinholdtsen 				return (-1);
2460c18ec02fSPetter Reinholdtsen 			}
2461c18ec02fSPetter Reinholdtsen 			printf("0x%02x ", data);
2462c18ec02fSPetter Reinholdtsen 			len--;
2463c18ec02fSPetter Reinholdtsen 		}
2464c18ec02fSPetter Reinholdtsen 		printf("\n");
2465c18ec02fSPetter Reinholdtsen 	}
2466c18ec02fSPetter Reinholdtsen 	/*** Chassis Info Area ***/
2467c18ec02fSPetter Reinholdtsen 	if (header.offset.chassis != 0) {
2468c18ec02fSPetter Reinholdtsen 		long offset = 0;
2469c18ec02fSPetter Reinholdtsen 		offset = header.offset.chassis * FACTOR_OFFSET;
2470c18ec02fSPetter Reinholdtsen 		ret = ipmi_ek_display_chassis_info_area(input_file, offset);
2471c18ec02fSPetter Reinholdtsen 	}
2472c18ec02fSPetter Reinholdtsen 	/*** Display FRU Board Info Area ***/
2473c18ec02fSPetter Reinholdtsen 	while (1) {
2474c18ec02fSPetter Reinholdtsen 		if (header.offset.board == 0) {
2475c18ec02fSPetter Reinholdtsen 			break;
2476c18ec02fSPetter Reinholdtsen 		}
2477c18ec02fSPetter Reinholdtsen 		ret = fseek(input_file,
2478c18ec02fSPetter Reinholdtsen 				(header.offset.board * FACTOR_OFFSET),
2479c18ec02fSPetter Reinholdtsen 				SEEK_SET);
2480c18ec02fSPetter Reinholdtsen 		if (feof(input_file)) {
2481c18ec02fSPetter Reinholdtsen 			break;
2482c18ec02fSPetter Reinholdtsen 		}
2483c18ec02fSPetter Reinholdtsen 		file_offset = ftell(input_file);
2484c18ec02fSPetter Reinholdtsen 		printf("%s\n", EQUAL_LINE_LIMITER);
2485c18ec02fSPetter Reinholdtsen 		printf("FRU Board Info Area\n");
2486c18ec02fSPetter Reinholdtsen 		printf("%s\n", EQUAL_LINE_LIMITER);
2487c18ec02fSPetter Reinholdtsen 
2488c18ec02fSPetter Reinholdtsen 		ret = fread(&data, 1, 1, input_file); /* Format version */
2489c18ec02fSPetter Reinholdtsen 		if ((ret != 1) || ferror(input_file)) {
2490c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid FRU Format Version!");
2491c18ec02fSPetter Reinholdtsen 			fclose(input_file);
2492c18ec02fSPetter Reinholdtsen 			return (-1);
2493c18ec02fSPetter Reinholdtsen 		}
2494c18ec02fSPetter Reinholdtsen 		printf("Format Version: %d\n", (data & 0x0f));
2495c18ec02fSPetter Reinholdtsen 		if (feof(input_file)) {
2496c18ec02fSPetter Reinholdtsen 			break;
2497c18ec02fSPetter Reinholdtsen 		}
2498c18ec02fSPetter Reinholdtsen 		ret = fread(&data, 1, 1, input_file); /* Board Area Length */
2499c18ec02fSPetter Reinholdtsen 		if ((ret != 1) || ferror(input_file)) {
2500c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid Board Area Length!");
2501c18ec02fSPetter Reinholdtsen 			fclose(input_file);
2502c18ec02fSPetter Reinholdtsen 			return (-1);
2503c18ec02fSPetter Reinholdtsen 		}
2504c18ec02fSPetter Reinholdtsen 		board_length = (data * FACTOR_OFFSET);
2505c18ec02fSPetter Reinholdtsen 		printf("Area Length: %d\n", board_length);
2506c18ec02fSPetter Reinholdtsen 		/* Decrease the length of board area by 1 byte of format version
2507c18ec02fSPetter Reinholdtsen 		 * and 1 byte for area length itself. the rest of this length will
2508c18ec02fSPetter Reinholdtsen 		 * be used to check for additional custom mfg. byte
2509c18ec02fSPetter Reinholdtsen 		 */
2510c18ec02fSPetter Reinholdtsen 		board_length -= 2;
2511c18ec02fSPetter Reinholdtsen 		if (feof(input_file)) {
2512c18ec02fSPetter Reinholdtsen 			break;
2513c18ec02fSPetter Reinholdtsen 		}
2514c18ec02fSPetter Reinholdtsen 		ret = fread(&lan_code, 1, 1, input_file); /* Language Code */
2515c18ec02fSPetter Reinholdtsen 		if ((ret != 1) || ferror(input_file)) {
2516c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid Language Code in input");
2517c18ec02fSPetter Reinholdtsen 			fclose(input_file);
2518c18ec02fSPetter Reinholdtsen 			return (-1);
2519c18ec02fSPetter Reinholdtsen 		}
2520c18ec02fSPetter Reinholdtsen 		printf("Language Code: %d\n", lan_code);
2521c18ec02fSPetter Reinholdtsen 		board_length--;
2522c18ec02fSPetter Reinholdtsen 		/* Board Mfg Date */
2523c18ec02fSPetter Reinholdtsen 		if (feof(input_file)) {
2524c18ec02fSPetter Reinholdtsen 			break;
2525c18ec02fSPetter Reinholdtsen 		}
2526c18ec02fSPetter Reinholdtsen 
2527c18ec02fSPetter Reinholdtsen 		ret = fread(mfg_date, SIZE_MFG_DATE, 1, input_file);
2528c18ec02fSPetter Reinholdtsen 		if (ret != 1) {
2529c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid Board Data.");
2530c18ec02fSPetter Reinholdtsen 			fclose(input_file);
2531c18ec02fSPetter Reinholdtsen 			return (-1);
2532c18ec02fSPetter Reinholdtsen 		}
2533c18ec02fSPetter Reinholdtsen 		tval = ((mfg_date[2] << 16) + (mfg_date[1] << 8)
2534c18ec02fSPetter Reinholdtsen 				+ (mfg_date[0]));
2535c18ec02fSPetter Reinholdtsen 		tval = tval * 60;
2536c18ec02fSPetter Reinholdtsen 		tval = tval + secs_from_1970_1996;
2537c18ec02fSPetter Reinholdtsen 		printf("Board Mfg Date: %ld, %s", tval,
2538c18ec02fSPetter Reinholdtsen 				asctime(localtime(&tval)));
2539c18ec02fSPetter Reinholdtsen 		board_length -= SIZE_MFG_DATE;
2540c18ec02fSPetter Reinholdtsen 		/* Board Mfg */
2541c18ec02fSPetter Reinholdtsen 		file_offset = ipmi_ek_display_board_info_area(
2542c18ec02fSPetter Reinholdtsen 				input_file, "Board Manufacture Data", &board_length);
2543c18ec02fSPetter Reinholdtsen 		ret = fseek(input_file, file_offset, SEEK_SET);
2544c18ec02fSPetter Reinholdtsen 		/* Board Product */
2545c18ec02fSPetter Reinholdtsen 		file_offset = ipmi_ek_display_board_info_area(
2546c18ec02fSPetter Reinholdtsen 				input_file, "Board Product Name", &board_length);
2547c18ec02fSPetter Reinholdtsen 		ret = fseek(input_file, file_offset, SEEK_SET);
2548c18ec02fSPetter Reinholdtsen 		/* Board Serial */
2549c18ec02fSPetter Reinholdtsen 		file_offset = ipmi_ek_display_board_info_area(
2550c18ec02fSPetter Reinholdtsen 				input_file, "Board Serial Number", &board_length);
2551c18ec02fSPetter Reinholdtsen 		ret = fseek(input_file, file_offset, SEEK_SET);
2552c18ec02fSPetter Reinholdtsen 		/* Board Part */
2553c18ec02fSPetter Reinholdtsen 		file_offset = ipmi_ek_display_board_info_area(
2554c18ec02fSPetter Reinholdtsen 				input_file, "Board Part Number", &board_length);
2555c18ec02fSPetter Reinholdtsen 		ret = fseek(input_file, file_offset, SEEK_SET);
2556c18ec02fSPetter Reinholdtsen 		/* FRU file ID */
2557c18ec02fSPetter Reinholdtsen 		file_offset = ipmi_ek_display_board_info_area(
2558c18ec02fSPetter Reinholdtsen 				input_file, "FRU File ID", &board_length);
2559c18ec02fSPetter Reinholdtsen 		ret = fseek(input_file, file_offset, SEEK_SET);
2560c18ec02fSPetter Reinholdtsen 		/* Additional Custom Mfg. */
2561c18ec02fSPetter Reinholdtsen 		file_offset = ipmi_ek_display_board_info_area(
2562c18ec02fSPetter Reinholdtsen 				input_file, "Custom", &board_length);
2563c18ec02fSPetter Reinholdtsen 		break;
2564c18ec02fSPetter Reinholdtsen 	}
2565c18ec02fSPetter Reinholdtsen 	/* Product Info Area */
2566c18ec02fSPetter Reinholdtsen 	if (header.offset.product && (!feof(input_file))) {
2567c18ec02fSPetter Reinholdtsen 		long offset = 0;
2568c18ec02fSPetter Reinholdtsen 		offset = header.offset.product * FACTOR_OFFSET;
2569c18ec02fSPetter Reinholdtsen 		ret = ipmi_ek_display_product_info_area(input_file,
2570c18ec02fSPetter Reinholdtsen 				offset);
2571c18ec02fSPetter Reinholdtsen 	}
2572c18ec02fSPetter Reinholdtsen 	fclose(input_file);
2573c18ec02fSPetter Reinholdtsen 	return 0;
2574c18ec02fSPetter Reinholdtsen }
2575c18ec02fSPetter Reinholdtsen 
2576c18ec02fSPetter Reinholdtsen /**************************************************************************
2577c18ec02fSPetter Reinholdtsen *
2578c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_chassis_info_area
2579c18ec02fSPetter Reinholdtsen *
2580c18ec02fSPetter Reinholdtsen * Description: this function displays detail format of product info area record
2581c18ec02fSPetter Reinholdtsen *               into humain readable text format
2582c18ec02fSPetter Reinholdtsen *
2583c18ec02fSPetter Reinholdtsen * Restriction: Reference: IPMI Platform Management FRU Information Storage
2584c18ec02fSPetter Reinholdtsen *                  Definition V1.0, Section 10
2585c18ec02fSPetter Reinholdtsen *
2586c18ec02fSPetter Reinholdtsen * Input: input_file: pointer to file stream
2587c18ec02fSPetter Reinholdtsen *         offset: start offset of chassis info area
2588c18ec02fSPetter Reinholdtsen *
2589c18ec02fSPetter Reinholdtsen * Output: None
2590c18ec02fSPetter Reinholdtsen *
2591c18ec02fSPetter Reinholdtsen * Global: None
2592c18ec02fSPetter Reinholdtsen *
2593c18ec02fSPetter Reinholdtsen * Return: None
2594c18ec02fSPetter Reinholdtsen *
2595c18ec02fSPetter Reinholdtsen ***************************************************************************/
2596c18ec02fSPetter Reinholdtsen static int
ipmi_ek_display_chassis_info_area(FILE * input_file,long offset)2597c18ec02fSPetter Reinholdtsen ipmi_ek_display_chassis_info_area(FILE *input_file, long offset)
2598c18ec02fSPetter Reinholdtsen {
2599c18ec02fSPetter Reinholdtsen 	size_t file_offset;
2600c18ec02fSPetter Reinholdtsen 	int ret = 0;
2601c18ec02fSPetter Reinholdtsen 	unsigned char data = 0;
2602c18ec02fSPetter Reinholdtsen 	unsigned char ch_len = 0;
2603c18ec02fSPetter Reinholdtsen 	unsigned char ch_type = 0;
2604c18ec02fSPetter Reinholdtsen 	unsigned int len;
2605c18ec02fSPetter Reinholdtsen 
2606c18ec02fSPetter Reinholdtsen 	if (input_file == NULL) {
2607c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "No file stream to read.");
2608c18ec02fSPetter Reinholdtsen 		return (-1);
2609c18ec02fSPetter Reinholdtsen 	}
2610c18ec02fSPetter Reinholdtsen 	printf("%s\n", EQUAL_LINE_LIMITER);
2611c18ec02fSPetter Reinholdtsen 	printf("Chassis Info Area\n");
2612c18ec02fSPetter Reinholdtsen 	printf("%s\n", EQUAL_LINE_LIMITER);
2613c18ec02fSPetter Reinholdtsen 	ret = fseek(input_file, offset, SEEK_SET);
2614c18ec02fSPetter Reinholdtsen 	if (feof(input_file)) {
2615c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid Chassis Info Area!");
2616c18ec02fSPetter Reinholdtsen 		return (-1);
2617c18ec02fSPetter Reinholdtsen 	}
2618c18ec02fSPetter Reinholdtsen 	ret = fread(&data, 1, 1, input_file);
2619c18ec02fSPetter Reinholdtsen 	if ((ret != 1) || ferror(input_file)) {
2620c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid Version Number!");
2621c18ec02fSPetter Reinholdtsen 		return (-1);
2622c18ec02fSPetter Reinholdtsen 	}
2623c18ec02fSPetter Reinholdtsen 	printf("Format Version Number: %d\n", (data & 0x0f));
2624c18ec02fSPetter Reinholdtsen 	ret = fread(&ch_len, 1, 1, input_file);
2625c18ec02fSPetter Reinholdtsen 	if ((ret != 1) || ferror(input_file)) {
2626c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid length!");
2627c18ec02fSPetter Reinholdtsen 		return (-1);
2628c18ec02fSPetter Reinholdtsen 	}
2629c18ec02fSPetter Reinholdtsen 	/* len is in factor of 8 bytes */
2630c18ec02fSPetter Reinholdtsen 	len = ch_len * 8;
2631c18ec02fSPetter Reinholdtsen 	printf("Area Length: %d\n", len);
2632c18ec02fSPetter Reinholdtsen 	len -= 2;
2633c18ec02fSPetter Reinholdtsen 	if (feof(input_file)) {
2634c18ec02fSPetter Reinholdtsen 		return (-1);
2635c18ec02fSPetter Reinholdtsen 	}
2636c18ec02fSPetter Reinholdtsen 	/* Chassis Type*/
2637c18ec02fSPetter Reinholdtsen 	ret = fread(&ch_type, 1, 1, input_file);
2638c18ec02fSPetter Reinholdtsen 	if ((ret != 1) || ferror(input_file)) {
2639c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid Chassis Type!");
2640c18ec02fSPetter Reinholdtsen 		return (-1);
2641c18ec02fSPetter Reinholdtsen 	}
2642c18ec02fSPetter Reinholdtsen 	printf("Chassis Type: %d\n", ch_type);
2643c18ec02fSPetter Reinholdtsen 	len--;
2644c18ec02fSPetter Reinholdtsen 	/* Chassis Part Number*/
2645c18ec02fSPetter Reinholdtsen 	file_offset = ipmi_ek_display_board_info_area(input_file,
2646c18ec02fSPetter Reinholdtsen 			"Chassis Part Number", &len);
2647c18ec02fSPetter Reinholdtsen 	ret = fseek(input_file, file_offset, SEEK_SET);
2648c18ec02fSPetter Reinholdtsen 	/* Chassis Serial */
2649c18ec02fSPetter Reinholdtsen 	file_offset = ipmi_ek_display_board_info_area(input_file,
2650c18ec02fSPetter Reinholdtsen 			"Chassis Serial Number", &len);
2651c18ec02fSPetter Reinholdtsen 	ret = fseek(input_file, file_offset, SEEK_SET);
2652c18ec02fSPetter Reinholdtsen 	/* Custom product info area */
2653c18ec02fSPetter Reinholdtsen 	file_offset = ipmi_ek_display_board_info_area(input_file,
2654c18ec02fSPetter Reinholdtsen 			"Custom", &len);
2655c18ec02fSPetter Reinholdtsen 	return 0;
2656c18ec02fSPetter Reinholdtsen }
2657c18ec02fSPetter Reinholdtsen 
2658c18ec02fSPetter Reinholdtsen /**************************************************************************
2659c18ec02fSPetter Reinholdtsen *
2660c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_board_info_area
2661c18ec02fSPetter Reinholdtsen *
2662c18ec02fSPetter Reinholdtsen * Description: this function displays board info area depending on board type
2663c18ec02fSPetter Reinholdtsen *               that pass in argument. Board type can be:
2664c18ec02fSPetter Reinholdtsen *               Manufacturer, Serial, Product or Part...
2665c18ec02fSPetter Reinholdtsen *
2666c18ec02fSPetter Reinholdtsen * Restriction: IPMI Platform Management FRU Information Storage
2667c18ec02fSPetter Reinholdtsen *                  Definition V1.0, Section 11
2668c18ec02fSPetter Reinholdtsen *
2669c18ec02fSPetter Reinholdtsen * Input: input_file: pointer to file stream
2670c18ec02fSPetter Reinholdtsen *         board_type: a string that contain board type
2671c18ec02fSPetter Reinholdtsen *         board_length: length of info area
2672c18ec02fSPetter Reinholdtsen *
2673c18ec02fSPetter Reinholdtsen * Output: None
2674c18ec02fSPetter Reinholdtsen *
2675c18ec02fSPetter Reinholdtsen * Global: None
2676c18ec02fSPetter Reinholdtsen *
2677c18ec02fSPetter Reinholdtsen * Return: the current position of input_file
2678c18ec02fSPetter Reinholdtsen *
2679c18ec02fSPetter Reinholdtsen ***************************************************************************/
2680c18ec02fSPetter Reinholdtsen static size_t
ipmi_ek_display_board_info_area(FILE * input_file,char * board_type,unsigned int * board_length)2681c18ec02fSPetter Reinholdtsen ipmi_ek_display_board_info_area(FILE *input_file, char *board_type,
2682c18ec02fSPetter Reinholdtsen 		unsigned int *board_length)
2683c18ec02fSPetter Reinholdtsen {
2684c18ec02fSPetter Reinholdtsen 	size_t file_offset;
2685c18ec02fSPetter Reinholdtsen 	int ret = 0;
2686c18ec02fSPetter Reinholdtsen 	unsigned char len = 0;
2687c18ec02fSPetter Reinholdtsen 	unsigned int size_board = 0;
2688c18ec02fSPetter Reinholdtsen 	if (input_file == NULL || board_type == NULL
2689c18ec02fSPetter Reinholdtsen 			|| board_length == NULL) {
2690c18ec02fSPetter Reinholdtsen 		return (size_t)(-1);
2691c18ec02fSPetter Reinholdtsen 	}
2692c18ec02fSPetter Reinholdtsen 	file_offset = ftell(input_file);
2693c18ec02fSPetter Reinholdtsen 
2694c18ec02fSPetter Reinholdtsen 	/* Board length*/
2695c18ec02fSPetter Reinholdtsen 	ret = fread(&len, 1, 1, input_file);
2696c18ec02fSPetter Reinholdtsen 	if ((ret != 1) || ferror(input_file)) {
2697c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid Length!");
2698c18ec02fSPetter Reinholdtsen 		goto out;
2699c18ec02fSPetter Reinholdtsen 	}
2700c18ec02fSPetter Reinholdtsen 	(*board_length)--;
2701c18ec02fSPetter Reinholdtsen 
2702c18ec02fSPetter Reinholdtsen 	/* Bit 5:0 of Board Mfg type represent legnth */
2703c18ec02fSPetter Reinholdtsen 	size_board = (len & 0x3f);
2704c18ec02fSPetter Reinholdtsen 	if (size_board == 0) {
2705c18ec02fSPetter Reinholdtsen 		printf("%s: None\n", board_type);
2706c18ec02fSPetter Reinholdtsen 		goto out;
2707c18ec02fSPetter Reinholdtsen 	}
2708c18ec02fSPetter Reinholdtsen 	if (strncmp(board_type, "Custom", 6 ) != 0) {
2709c18ec02fSPetter Reinholdtsen 		unsigned char *data;
2710c18ec02fSPetter Reinholdtsen 		unsigned int i = 0;
2711c18ec02fSPetter Reinholdtsen 		data = malloc(size_board);
2712c18ec02fSPetter Reinholdtsen 		if (data == NULL) {
2713c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "ipmitool: malloc failure");
2714c18ec02fSPetter Reinholdtsen 			return (size_t)(-1);
2715c18ec02fSPetter Reinholdtsen 		}
2716c18ec02fSPetter Reinholdtsen 		ret = fread(data, size_board, 1, input_file);
2717c18ec02fSPetter Reinholdtsen 		if ((ret != 1) || ferror(input_file)) {
2718c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid board type size!");
2719c18ec02fSPetter Reinholdtsen 			free(data);
2720c18ec02fSPetter Reinholdtsen 			data = NULL;
2721c18ec02fSPetter Reinholdtsen 			goto out;
2722c18ec02fSPetter Reinholdtsen 		}
2723c18ec02fSPetter Reinholdtsen 		printf("%s type: 0x%02x\n", board_type, len);
2724c18ec02fSPetter Reinholdtsen 		printf("%s: ", board_type);
2725c18ec02fSPetter Reinholdtsen 		for (i = 0; i < size_board; i++) {
2726c18ec02fSPetter Reinholdtsen 			if ((len & TYPE_CODE) == TYPE_CODE) {
2727c18ec02fSPetter Reinholdtsen 				printf("%c", data[i]);
2728c18ec02fSPetter Reinholdtsen 			} else {
2729c18ec02fSPetter Reinholdtsen 				/* other than language code (binary, BCD,
2730c18ec02fSPetter Reinholdtsen 				 * ASCII 6 bit...) is not supported
2731c18ec02fSPetter Reinholdtsen 				 */
2732c18ec02fSPetter Reinholdtsen 				printf("%02x", data[i]);
2733c18ec02fSPetter Reinholdtsen 			}
2734c18ec02fSPetter Reinholdtsen 		}
2735c18ec02fSPetter Reinholdtsen 		printf("\n");
2736c18ec02fSPetter Reinholdtsen 		free(data);
2737c18ec02fSPetter Reinholdtsen 		data = NULL;
2738c18ec02fSPetter Reinholdtsen 		(*board_length) -= size_board;
2739c18ec02fSPetter Reinholdtsen 		goto out;
2740c18ec02fSPetter Reinholdtsen 	}
2741c18ec02fSPetter Reinholdtsen 	while (!feof(input_file)) {
2742c18ec02fSPetter Reinholdtsen 		if (len == NO_MORE_INFO_FIELD) {
2743c18ec02fSPetter Reinholdtsen 			unsigned char padding;
2744c18ec02fSPetter Reinholdtsen 			unsigned char checksum = 0;
2745c18ec02fSPetter Reinholdtsen 			/* take the rest of data in the area minus 1 byte of
2746c18ec02fSPetter Reinholdtsen 			 * checksum
2747c18ec02fSPetter Reinholdtsen 			 */
2748c18ec02fSPetter Reinholdtsen 			printf("Additional Custom Mfg. length: 0x%02x\n", len);
2749c18ec02fSPetter Reinholdtsen 			padding = (*board_length) - 1;
2750c18ec02fSPetter Reinholdtsen 			if ((padding > 0) && (!feof(input_file))) {
2751c18ec02fSPetter Reinholdtsen 				printf("Unused space: %d (bytes)\n", padding);
2752c18ec02fSPetter Reinholdtsen 				fseek(input_file, padding, SEEK_CUR);
2753c18ec02fSPetter Reinholdtsen 			}
2754c18ec02fSPetter Reinholdtsen 			ret = fread(&checksum, 1, 1, input_file);
2755c18ec02fSPetter Reinholdtsen 			if ((ret != 1) || ferror(input_file)) {
2756c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Invalid Checksum!");
2757c18ec02fSPetter Reinholdtsen 				goto out;
2758c18ec02fSPetter Reinholdtsen 			}
2759c18ec02fSPetter Reinholdtsen 			printf("Checksum: 0x%02x\n", checksum);
2760c18ec02fSPetter Reinholdtsen 			goto out;
2761c18ec02fSPetter Reinholdtsen 		}
2762c18ec02fSPetter Reinholdtsen 		printf("Additional Custom Mfg. length: 0x%02x\n", len);
2763c18ec02fSPetter Reinholdtsen 		if ((size_board > 0) && (size_board < (*board_length))) {
2764c18ec02fSPetter Reinholdtsen 			unsigned char * additional_data = NULL;
2765c18ec02fSPetter Reinholdtsen 			unsigned int i = 0;
2766c18ec02fSPetter Reinholdtsen 			additional_data = malloc(size_board);
2767c18ec02fSPetter Reinholdtsen 			if (additional_data == NULL) {
2768c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "ipmitool: malloc failure");
2769c18ec02fSPetter Reinholdtsen 				return (size_t)(-1);
2770c18ec02fSPetter Reinholdtsen 			}
2771c18ec02fSPetter Reinholdtsen 
2772c18ec02fSPetter Reinholdtsen 			ret = fread(additional_data, size_board, 1, input_file);
2773c18ec02fSPetter Reinholdtsen 			if ((ret != 1) || ferror(input_file)) {
2774c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Invalid Additional Data!");
2775*61db4df6SZdenek Styblik 				if (additional_data != NULL) {
2776*61db4df6SZdenek Styblik 					free(additional_data);
2777*61db4df6SZdenek Styblik 					additional_data = NULL;
2778*61db4df6SZdenek Styblik 				}
2779c18ec02fSPetter Reinholdtsen 				goto out;
2780c18ec02fSPetter Reinholdtsen 			}
2781c18ec02fSPetter Reinholdtsen 			printf("Additional Custom Mfg. Data: %02x",
2782c18ec02fSPetter Reinholdtsen 					additional_data[0]);
2783c18ec02fSPetter Reinholdtsen 			for (i = 1; i < size_board; i++) {
2784c18ec02fSPetter Reinholdtsen 				printf("-%02x", additional_data[i]);
2785c18ec02fSPetter Reinholdtsen 			}
2786c18ec02fSPetter Reinholdtsen 			printf("\n");
2787c18ec02fSPetter Reinholdtsen 			free(additional_data);
2788c18ec02fSPetter Reinholdtsen 			additional_data = NULL;
2789c18ec02fSPetter Reinholdtsen 			(*board_length) -= size_board;
2790c18ec02fSPetter Reinholdtsen 		}
2791c18ec02fSPetter Reinholdtsen 		else {
2792c18ec02fSPetter Reinholdtsen 			printf("No Additional Custom Mfg. %d\n", *board_length);
2793c18ec02fSPetter Reinholdtsen 			goto out;
2794c18ec02fSPetter Reinholdtsen 		}
2795c18ec02fSPetter Reinholdtsen 	}
2796c18ec02fSPetter Reinholdtsen 
2797c18ec02fSPetter Reinholdtsen out:
2798c18ec02fSPetter Reinholdtsen 	file_offset = ftell(input_file);
2799c18ec02fSPetter Reinholdtsen 	return file_offset;
2800c18ec02fSPetter Reinholdtsen }
2801c18ec02fSPetter Reinholdtsen 
2802c18ec02fSPetter Reinholdtsen /**************************************************************************
2803c18ec02fSPetter Reinholdtsen *
2804c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_product_info_area
2805c18ec02fSPetter Reinholdtsen *
2806c18ec02fSPetter Reinholdtsen * Description: this function displays detail format of product info area record
2807c18ec02fSPetter Reinholdtsen *               into humain readable text format
2808c18ec02fSPetter Reinholdtsen *
2809c18ec02fSPetter Reinholdtsen * Restriction: Reference: IPMI Platform Management FRU Information Storage
2810c18ec02fSPetter Reinholdtsen *                  Definition V1.0, Section 12
2811c18ec02fSPetter Reinholdtsen *
2812c18ec02fSPetter Reinholdtsen * Input: input_file: pointer to file stream
2813c18ec02fSPetter Reinholdtsen *         offset: start offset of product info area
2814c18ec02fSPetter Reinholdtsen *
2815c18ec02fSPetter Reinholdtsen * Output: None
2816c18ec02fSPetter Reinholdtsen *
2817c18ec02fSPetter Reinholdtsen * Global: None
2818c18ec02fSPetter Reinholdtsen *
2819c18ec02fSPetter Reinholdtsen * Return: None
2820c18ec02fSPetter Reinholdtsen *
2821c18ec02fSPetter Reinholdtsen ***************************************************************************/
2822c18ec02fSPetter Reinholdtsen static int
ipmi_ek_display_product_info_area(FILE * input_file,long offset)2823c18ec02fSPetter Reinholdtsen ipmi_ek_display_product_info_area(FILE *input_file, long offset)
2824c18ec02fSPetter Reinholdtsen {
2825c18ec02fSPetter Reinholdtsen 	size_t file_offset;
2826c18ec02fSPetter Reinholdtsen 	int ret = 0;
2827c18ec02fSPetter Reinholdtsen 	unsigned char ch_len = 0;
2828c18ec02fSPetter Reinholdtsen 	unsigned char data = 0;
2829c18ec02fSPetter Reinholdtsen 	unsigned int len = 0;
2830c18ec02fSPetter Reinholdtsen 
2831c18ec02fSPetter Reinholdtsen 	if (input_file == NULL) {
2832c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "No file stream to read.");
2833c18ec02fSPetter Reinholdtsen 		return (-1);
2834c18ec02fSPetter Reinholdtsen 	}
2835c18ec02fSPetter Reinholdtsen 	file_offset = ftell(input_file);
2836c18ec02fSPetter Reinholdtsen 	printf("%s\n", EQUAL_LINE_LIMITER);
2837c18ec02fSPetter Reinholdtsen 	printf("Product Info Area\n");
2838c18ec02fSPetter Reinholdtsen 	printf("%s\n", EQUAL_LINE_LIMITER);
2839c18ec02fSPetter Reinholdtsen 	ret = fseek(input_file, offset, SEEK_SET);
2840c18ec02fSPetter Reinholdtsen 	if (feof(input_file)) {
2841c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid Product Info Area!");
2842c18ec02fSPetter Reinholdtsen 		return (-1);
2843c18ec02fSPetter Reinholdtsen 	}
2844c18ec02fSPetter Reinholdtsen 	ret = fread(&data, 1, 1, input_file);
2845c18ec02fSPetter Reinholdtsen 	if ((ret != 1) || ferror(input_file)) {
2846c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid Data!");
2847c18ec02fSPetter Reinholdtsen 		return (-1);
2848c18ec02fSPetter Reinholdtsen 	}
2849c18ec02fSPetter Reinholdtsen 	printf("Format Version Number: %d\n", (data & 0x0f));
2850c18ec02fSPetter Reinholdtsen 	if (feof(input_file)) {
2851c18ec02fSPetter Reinholdtsen 		return (-1);
2852c18ec02fSPetter Reinholdtsen 	}
2853c18ec02fSPetter Reinholdtsen 	/* Have to read this into a char or else
2854c18ec02fSPetter Reinholdtsen 	 * it ends up byte swapped on big endian machines */
2855c18ec02fSPetter Reinholdtsen 	ret = fread(&ch_len, 1, 1, input_file);
2856c18ec02fSPetter Reinholdtsen 	if ((ret != 1) || ferror(input_file)) {
2857c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid Length!");
2858c18ec02fSPetter Reinholdtsen 		return (-1);
2859c18ec02fSPetter Reinholdtsen 	}
2860c18ec02fSPetter Reinholdtsen 	/* length is in factor of 8 bytes */
2861c18ec02fSPetter Reinholdtsen 	len = ch_len * 8;
2862c18ec02fSPetter Reinholdtsen 	printf("Area Length: %d\n", len);
2863c18ec02fSPetter Reinholdtsen 	len -= 2; /* -1 byte of format version and -1 byte itself */
2864c18ec02fSPetter Reinholdtsen 
2865c18ec02fSPetter Reinholdtsen 	ret = fread(&data, 1, 1, input_file);
2866c18ec02fSPetter Reinholdtsen 	if ((ret != 1) || ferror(input_file)) {
2867c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid Length!");
2868c18ec02fSPetter Reinholdtsen 		return (-1);
2869c18ec02fSPetter Reinholdtsen 	}
2870c18ec02fSPetter Reinholdtsen 
2871c18ec02fSPetter Reinholdtsen 	fread(&data, 1, 1, input_file);
2872c18ec02fSPetter Reinholdtsen 	printf("Language Code: %d\n", data);
2873c18ec02fSPetter Reinholdtsen 	len--;
2874c18ec02fSPetter Reinholdtsen 	/* Product Mfg */
2875c18ec02fSPetter Reinholdtsen 	file_offset = ipmi_ek_display_board_info_area(input_file,
2876c18ec02fSPetter Reinholdtsen 			"Product Manufacture Data", &len);
2877c18ec02fSPetter Reinholdtsen 	ret = fseek(input_file, file_offset, SEEK_SET);
2878c18ec02fSPetter Reinholdtsen 	/* Product Name */
2879c18ec02fSPetter Reinholdtsen 	file_offset = ipmi_ek_display_board_info_area(input_file,
2880c18ec02fSPetter Reinholdtsen 			"Product Name", &len);
2881c18ec02fSPetter Reinholdtsen 	ret = fseek(input_file, file_offset, SEEK_SET);
2882c18ec02fSPetter Reinholdtsen 	/* Product Part */
2883c18ec02fSPetter Reinholdtsen 	file_offset = ipmi_ek_display_board_info_area(input_file,
2884c18ec02fSPetter Reinholdtsen 			"Product Part/Model Number", &len);
2885c18ec02fSPetter Reinholdtsen 	ret = fseek(input_file, file_offset, SEEK_SET);
2886c18ec02fSPetter Reinholdtsen 	/* Product Version */
2887c18ec02fSPetter Reinholdtsen 	file_offset = ipmi_ek_display_board_info_area(input_file,
2888c18ec02fSPetter Reinholdtsen 			"Product Version", &len);
2889c18ec02fSPetter Reinholdtsen 	ret = fseek(input_file, file_offset, SEEK_SET);
2890c18ec02fSPetter Reinholdtsen 	/* Product Serial */
2891c18ec02fSPetter Reinholdtsen 	file_offset = ipmi_ek_display_board_info_area(input_file,
2892c18ec02fSPetter Reinholdtsen 			"Product Serial Number", &len);
2893c18ec02fSPetter Reinholdtsen 	ret = fseek(input_file, file_offset, SEEK_SET);
2894c18ec02fSPetter Reinholdtsen 	/* Product Asset Tag */
2895c18ec02fSPetter Reinholdtsen 	file_offset = ipmi_ek_display_board_info_area(input_file,
2896c18ec02fSPetter Reinholdtsen 			"Asset Tag", &len);
2897c18ec02fSPetter Reinholdtsen 	ret = fseek(input_file, file_offset, SEEK_SET);
2898c18ec02fSPetter Reinholdtsen 	/* FRU file ID */
2899c18ec02fSPetter Reinholdtsen 	file_offset = ipmi_ek_display_board_info_area(input_file,
2900c18ec02fSPetter Reinholdtsen 			"FRU File ID", &len);
2901c18ec02fSPetter Reinholdtsen 	ret = fseek(input_file, file_offset, SEEK_SET);
2902c18ec02fSPetter Reinholdtsen 	/* Custom product info area */
2903c18ec02fSPetter Reinholdtsen 	file_offset = ipmi_ek_display_board_info_area(input_file,
2904c18ec02fSPetter Reinholdtsen 			"Custom", &len);
2905c18ec02fSPetter Reinholdtsen 	return 0;
2906c18ec02fSPetter Reinholdtsen }
2907c18ec02fSPetter Reinholdtsen 
2908c18ec02fSPetter Reinholdtsen /**************************************************************************
2909c18ec02fSPetter Reinholdtsen *
2910c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_record
2911c18ec02fSPetter Reinholdtsen *
2912c18ec02fSPetter Reinholdtsen * Description: this function displays FRU multi record information.
2913c18ec02fSPetter Reinholdtsen *
2914c18ec02fSPetter Reinholdtsen * Restriction: None
2915c18ec02fSPetter Reinholdtsen *
2916c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record
2917c18ec02fSPetter Reinholdtsen *        list_head: a pointer to header of the list
2918c18ec02fSPetter Reinholdtsen *        list_last: a pointer to tale of the list
2919c18ec02fSPetter Reinholdtsen *
2920c18ec02fSPetter Reinholdtsen * Output: None
2921c18ec02fSPetter Reinholdtsen *
2922c18ec02fSPetter Reinholdtsen * Global: None
2923c18ec02fSPetter Reinholdtsen *
2924c18ec02fSPetter Reinholdtsen * Return: None
2925c18ec02fSPetter Reinholdtsen *
2926c18ec02fSPetter Reinholdtsen ***************************************************************************/
2927c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_record(struct ipmi_ek_multi_header * record,struct ipmi_ek_multi_header * list_head,struct ipmi_ek_multi_header * list_last)2928c18ec02fSPetter Reinholdtsen ipmi_ek_display_record(struct ipmi_ek_multi_header *record,
2929c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header *list_head,
2930c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header *list_last)
2931c18ec02fSPetter Reinholdtsen {
2932c18ec02fSPetter Reinholdtsen 	if (list_head == NULL) {
2933c18ec02fSPetter Reinholdtsen 		printf("***empty list***\n");
2934b37b9149SZdenek Styblik 		return;
2935c18ec02fSPetter Reinholdtsen 	}
2936c18ec02fSPetter Reinholdtsen 	printf("%s\n", EQUAL_LINE_LIMITER);
2937c18ec02fSPetter Reinholdtsen 	printf("FRU Multi Info area\n");
2938c18ec02fSPetter Reinholdtsen 	printf("%s\n", EQUAL_LINE_LIMITER);
2939c18ec02fSPetter Reinholdtsen 	for (record = list_head; record != NULL; record = record->next) {
2940c18ec02fSPetter Reinholdtsen 		printf("Record Type ID: 0x%02x\n", record->header.type);
2941b37b9149SZdenek Styblik 		printf("Record Format version: 0x%02x\n",
2942b37b9149SZdenek Styblik 				record->header.format);
2943b37b9149SZdenek Styblik 		if (record->header.len <= PICMG_ID_OFFSET) {
2944b37b9149SZdenek Styblik 			continue;
2945b37b9149SZdenek Styblik 		}
2946b37b9149SZdenek Styblik 		/* In picmg3.0 specification, picmg record
2947b37b9149SZdenek Styblik 		 * id lower than 4 or greater than 0x2d
2948b37b9149SZdenek Styblik 		 * isn't supported
2949c18ec02fSPetter Reinholdtsen 		 */
2950c18ec02fSPetter Reinholdtsen 		#define PICMG_ID_LOWER_LIMIT  0x04
2951c18ec02fSPetter Reinholdtsen 		#define PICMG_ID_UPPER_LIMIT  0x2d
2952c18ec02fSPetter Reinholdtsen 		unsigned char picmg_id;
2953c18ec02fSPetter Reinholdtsen 
2954c18ec02fSPetter Reinholdtsen 		picmg_id = record->data[PICMG_ID_OFFSET];
2955b37b9149SZdenek Styblik 		printf("Manufacturer ID: %02x%02x%02x h\n",
2956b37b9149SZdenek Styblik 				record->data[2], record->data[1],
2957b37b9149SZdenek Styblik 				record->data[0]);
2958c18ec02fSPetter Reinholdtsen 		if ((picmg_id < PICMG_ID_LOWER_LIMIT)
2959b37b9149SZdenek Styblik 				|| (picmg_id > PICMG_ID_UPPER_LIMIT)) {
2960c18ec02fSPetter Reinholdtsen 			printf("Picmg record ID: Unsupported {0x%02x}\n", picmg_id);
2961b37b9149SZdenek Styblik 		} else {
2962c18ec02fSPetter Reinholdtsen 			printf("Picmg record ID: %s {0x%02x}\n",
2963c18ec02fSPetter Reinholdtsen 					val2str(picmg_id, ipmi_ekanalyzer_picmg_record_id),
2964c18ec02fSPetter Reinholdtsen 					picmg_id);
2965c18ec02fSPetter Reinholdtsen 		}
2966c18ec02fSPetter Reinholdtsen 		switch (picmg_id) {
2967c18ec02fSPetter Reinholdtsen 		case FRU_PICMG_BACKPLANE_P2P: /*0x04*/
2968c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_backplane_p2p_record (record);
2969c18ec02fSPetter Reinholdtsen 			break;
2970c18ec02fSPetter Reinholdtsen 		case FRU_PICMG_ADDRESS_TABLE: /*0x10*/
2971c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_address_table_record (record);
2972c18ec02fSPetter Reinholdtsen 			break;
2973c18ec02fSPetter Reinholdtsen 		case FRU_PICMG_SHELF_POWER_DIST: /*0x11*/
2974c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_shelf_power_distribution_record (record);
2975c18ec02fSPetter Reinholdtsen 			break;
2976c18ec02fSPetter Reinholdtsen 		case FRU_PICMG_SHELF_ACTIVATION: /*/0x12*/
2977c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_shelf_activation_record (record);
2978c18ec02fSPetter Reinholdtsen 			break;
2979c18ec02fSPetter Reinholdtsen 		case FRU_PICMG_SHMC_IP_CONN: /*0x13*/
2980c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_shelf_ip_connection_record (record);
2981c18ec02fSPetter Reinholdtsen 			break;
2982c18ec02fSPetter Reinholdtsen 		case FRU_PICMG_BOARD_P2P: /*0x14*/
2983c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_board_p2p_record (record);
2984c18ec02fSPetter Reinholdtsen 			break;
2985c18ec02fSPetter Reinholdtsen 		case FRU_RADIAL_IPMB0_LINK_MAPPING: /*0x15*/
2986c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_radial_ipmb0_record (record);
2987c18ec02fSPetter Reinholdtsen 			break;
2988c18ec02fSPetter Reinholdtsen 		case FRU_AMC_CURRENT: /*0x16*/
2989c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_amc_current_record (record);
2990c18ec02fSPetter Reinholdtsen 			break;
2991c18ec02fSPetter Reinholdtsen 		case FRU_AMC_ACTIVATION: /*0x17*/
2992c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_amc_activation_record (record);
2993c18ec02fSPetter Reinholdtsen 			break;
2994c18ec02fSPetter Reinholdtsen 		case FRU_AMC_CARRIER_P2P: /*0x18*/
2995c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_carrier_connectivity (record);
2996c18ec02fSPetter Reinholdtsen 			break;
2997c18ec02fSPetter Reinholdtsen 		case FRU_AMC_P2P: /*0x19*/
2998c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_amc_p2p_record (record);
2999c18ec02fSPetter Reinholdtsen 			break;
3000c18ec02fSPetter Reinholdtsen 		case FRU_AMC_CARRIER_INFO: /*0x1a*/
3001c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_amc_carrier_info_record (record);
3002c18ec02fSPetter Reinholdtsen 			break;
3003c18ec02fSPetter Reinholdtsen 		case FRU_PICMG_CLK_CARRIER_P2P: /*0x2c*/
3004c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_clock_carrier_p2p_record (record);
3005c18ec02fSPetter Reinholdtsen 			break;
3006c18ec02fSPetter Reinholdtsen 		case FRU_PICMG_CLK_CONFIG: /*0x2d*/
3007c18ec02fSPetter Reinholdtsen 			ipmi_ek_display_clock_config_record (record);
3008c18ec02fSPetter Reinholdtsen 			break;
3009c18ec02fSPetter Reinholdtsen 		default:
3010c18ec02fSPetter Reinholdtsen 			if (verbose > 0) {
3011c18ec02fSPetter Reinholdtsen 				int i;
3012b37b9149SZdenek Styblik 				printf("%02x %02x %02x %02x %02x ",
3013b37b9149SZdenek Styblik 						record->header.type,
3014b37b9149SZdenek Styblik 						record->header.format,
3015b37b9149SZdenek Styblik 						record->header.len,
3016c18ec02fSPetter Reinholdtsen 						record->header.record_checksum,
3017c18ec02fSPetter Reinholdtsen 						record->header.header_checksum);
3018c18ec02fSPetter Reinholdtsen 				for (i = 0; i < record->header.len; i++) {
3019c18ec02fSPetter Reinholdtsen 					printf("%02x ", record->data[i]);
3020c18ec02fSPetter Reinholdtsen 				}
3021c18ec02fSPetter Reinholdtsen 				printf("\n");
3022c18ec02fSPetter Reinholdtsen 			}
3023c18ec02fSPetter Reinholdtsen 			break;
3024c18ec02fSPetter Reinholdtsen 		}
3025c18ec02fSPetter Reinholdtsen 		printf("%s\n", STAR_LINE_LIMITER);
3026c18ec02fSPetter Reinholdtsen 	}
3027c18ec02fSPetter Reinholdtsen }
3028c18ec02fSPetter Reinholdtsen 
3029c18ec02fSPetter Reinholdtsen /**************************************************************************
3030c18ec02fSPetter Reinholdtsen *
3031c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_backplane_p2p_record
3032c18ec02fSPetter Reinholdtsen *
3033c18ec02fSPetter Reinholdtsen * Description: this function displays backplane p2p record.
3034c18ec02fSPetter Reinholdtsen *
3035c18ec02fSPetter Reinholdtsen * Restriction: Reference: PICMG 3.0 Specification Table 3-40
3036c18ec02fSPetter Reinholdtsen *
3037c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3038c18ec02fSPetter Reinholdtsen *
3039c18ec02fSPetter Reinholdtsen * Output: None
3040c18ec02fSPetter Reinholdtsen *
3041c18ec02fSPetter Reinholdtsen * Global: None
3042c18ec02fSPetter Reinholdtsen *
3043c18ec02fSPetter Reinholdtsen * Return: None
3044c18ec02fSPetter Reinholdtsen *
3045c18ec02fSPetter Reinholdtsen ***************************************************************************/
3046c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_backplane_p2p_record(struct ipmi_ek_multi_header * record)3047c18ec02fSPetter Reinholdtsen ipmi_ek_display_backplane_p2p_record(struct ipmi_ek_multi_header *record)
3048c18ec02fSPetter Reinholdtsen {
3049c18ec02fSPetter Reinholdtsen 	uint8_t index;
3050c18ec02fSPetter Reinholdtsen 	int offset = START_DATA_OFFSET;
3051b37b9149SZdenek Styblik 	struct fru_picmgext_slot_desc *slot_d =
3052b37b9149SZdenek Styblik 		(struct fru_picmgext_slot_desc*)&record->data[offset];
3053c18ec02fSPetter Reinholdtsen 
3054c18ec02fSPetter Reinholdtsen 	offset += sizeof(struct fru_picmgext_slot_desc);
3055c18ec02fSPetter Reinholdtsen 	while (offset <= record->header.len) {
3056c18ec02fSPetter Reinholdtsen 		printf("   Channel Type: ");
3057b37b9149SZdenek Styblik 		switch (slot_d->chan_type) {
3058c18ec02fSPetter Reinholdtsen 		case 0x00:
3059c18ec02fSPetter Reinholdtsen 		case 0x07:
3060c18ec02fSPetter Reinholdtsen 			printf("PICMG 2.9\n");
3061c18ec02fSPetter Reinholdtsen 			break;
3062c18ec02fSPetter Reinholdtsen 		case 0x08:
3063c18ec02fSPetter Reinholdtsen 			printf("Single Port Fabric IF\n");
3064c18ec02fSPetter Reinholdtsen 			break;
3065c18ec02fSPetter Reinholdtsen 		case 0x09:
3066c18ec02fSPetter Reinholdtsen 			printf("Double Port Fabric IF\n");
3067c18ec02fSPetter Reinholdtsen 			break;
3068c18ec02fSPetter Reinholdtsen 		case 0x0a:
3069c18ec02fSPetter Reinholdtsen 			printf("Full Channel Fabric IF\n");
3070c18ec02fSPetter Reinholdtsen 			break;
3071c18ec02fSPetter Reinholdtsen 		case 0x0b:
3072c18ec02fSPetter Reinholdtsen 			printf("Base IF\n");
3073c18ec02fSPetter Reinholdtsen 			break;
3074c18ec02fSPetter Reinholdtsen 		case 0x0c:
3075c18ec02fSPetter Reinholdtsen 			printf("Update Channel IF\n");
3076c18ec02fSPetter Reinholdtsen 			break;
3077c18ec02fSPetter Reinholdtsen 		default:
3078c18ec02fSPetter Reinholdtsen 			printf("Unknown IF\n");
3079c18ec02fSPetter Reinholdtsen 			break;
3080c18ec02fSPetter Reinholdtsen 		}
3081c18ec02fSPetter Reinholdtsen 		printf("   Slot Address:  %02x\n", slot_d->slot_addr);
3082c18ec02fSPetter Reinholdtsen 		printf("   Channel Count: %i\n", slot_d->chn_count);
3083c18ec02fSPetter Reinholdtsen 		for (index = 0; index < (slot_d->chn_count); index++) {
3084b37b9149SZdenek Styblik 			struct fru_picmgext_chn_desc *d =
3085b37b9149SZdenek Styblik 				(struct fru_picmgext_chn_desc *)&record->data[offset];
3086c18ec02fSPetter Reinholdtsen 			if (verbose) {
3087c18ec02fSPetter Reinholdtsen 				printf("\t"
3088c18ec02fSPetter Reinholdtsen 						"Chn: %02x   -->   "
3089c18ec02fSPetter Reinholdtsen 						"Chn: %02x in "
3090c18ec02fSPetter Reinholdtsen 						"Slot: %02x\n",
3091b37b9149SZdenek Styblik 						d->local_chn,
3092b37b9149SZdenek Styblik 						d->remote_chn,
3093b37b9149SZdenek Styblik 						d->remote_slot);
3094c18ec02fSPetter Reinholdtsen 			}
3095c18ec02fSPetter Reinholdtsen 			offset += sizeof(struct fru_picmgext_chn_desc);
3096c18ec02fSPetter Reinholdtsen 		}
3097c18ec02fSPetter Reinholdtsen 		slot_d = (struct fru_picmgext_slot_desc*)&record->data[offset];
3098c18ec02fSPetter Reinholdtsen 		offset += sizeof(struct fru_picmgext_slot_desc);
3099c18ec02fSPetter Reinholdtsen 	}
3100c18ec02fSPetter Reinholdtsen }
3101c18ec02fSPetter Reinholdtsen 
3102c18ec02fSPetter Reinholdtsen /**************************************************************************
3103c18ec02fSPetter Reinholdtsen *
3104c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_address_table_record
3105c18ec02fSPetter Reinholdtsen *
3106c18ec02fSPetter Reinholdtsen * Description: this function displays address table record.
3107c18ec02fSPetter Reinholdtsen *
3108c18ec02fSPetter Reinholdtsen * Restriction: Reference: PICMG 3.0 Specification Table 3-6
3109c18ec02fSPetter Reinholdtsen *
3110c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3111c18ec02fSPetter Reinholdtsen *
3112c18ec02fSPetter Reinholdtsen * Output: None
3113c18ec02fSPetter Reinholdtsen *
3114c18ec02fSPetter Reinholdtsen * Global: None
3115c18ec02fSPetter Reinholdtsen *
3116c18ec02fSPetter Reinholdtsen * Return: None
3117c18ec02fSPetter Reinholdtsen *
3118c18ec02fSPetter Reinholdtsen ***************************************************************************/
3119c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_address_table_record(struct ipmi_ek_multi_header * record)3120c18ec02fSPetter Reinholdtsen ipmi_ek_display_address_table_record(struct ipmi_ek_multi_header *record)
3121c18ec02fSPetter Reinholdtsen {
3122b37b9149SZdenek Styblik #define SIZE_SHELF_ADDRESS_BYTE 20
3123c18ec02fSPetter Reinholdtsen 	unsigned char entries = 0;
3124c18ec02fSPetter Reinholdtsen 	unsigned char i;
3125c18ec02fSPetter Reinholdtsen 	int offset = START_DATA_OFFSET;
3126c18ec02fSPetter Reinholdtsen 
3127c18ec02fSPetter Reinholdtsen 	printf("   Type/Len:    0x%02x\n", record->data[offset++]);
3128c18ec02fSPetter Reinholdtsen 	printf("   Shelf Addr: ");
3129c18ec02fSPetter Reinholdtsen 	for (i = 0; i < SIZE_SHELF_ADDRESS_BYTE; i++) {
3130c18ec02fSPetter Reinholdtsen 		printf("0x%02x ", record->data[offset++]);
3131c18ec02fSPetter Reinholdtsen 	}
3132c18ec02fSPetter Reinholdtsen 	printf("\n");
3133c18ec02fSPetter Reinholdtsen 	entries = record->data[offset++];
3134c18ec02fSPetter Reinholdtsen 	printf("   Addr Table Entries count: 0x%02x\n", entries);
3135c18ec02fSPetter Reinholdtsen 	for (i = 0; i < entries; i++) {
3136c18ec02fSPetter Reinholdtsen 		printf("\tHWAddr: 0x%02x  - SiteNum: 0x%02x - SiteType: 0x%02x \n",
3137c18ec02fSPetter Reinholdtsen 				record->data[offset+0],
3138c18ec02fSPetter Reinholdtsen 				record->data[offset+1],
3139c18ec02fSPetter Reinholdtsen 				record->data[offset+2]);
3140c18ec02fSPetter Reinholdtsen 		offset += 3;
3141c18ec02fSPetter Reinholdtsen 	}
3142c18ec02fSPetter Reinholdtsen }
3143c18ec02fSPetter Reinholdtsen 
3144c18ec02fSPetter Reinholdtsen /**************************************************************************
3145c18ec02fSPetter Reinholdtsen *
3146c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_shelf_power_distribution_record
3147c18ec02fSPetter Reinholdtsen *
3148c18ec02fSPetter Reinholdtsen * Description: this function displays shelf power distribution record.
3149c18ec02fSPetter Reinholdtsen *
3150c18ec02fSPetter Reinholdtsen * Restriction: Reference: PICMG 3.0 Specification Table 3-70
3151c18ec02fSPetter Reinholdtsen *
3152c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3153c18ec02fSPetter Reinholdtsen *
3154c18ec02fSPetter Reinholdtsen * Output: None
3155c18ec02fSPetter Reinholdtsen *
3156c18ec02fSPetter Reinholdtsen * Global: None
3157c18ec02fSPetter Reinholdtsen *
3158c18ec02fSPetter Reinholdtsen * Return: None
3159c18ec02fSPetter Reinholdtsen *
3160c18ec02fSPetter Reinholdtsen ***************************************************************************/
3161c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_shelf_power_distribution_record(struct ipmi_ek_multi_header * record)3162c18ec02fSPetter Reinholdtsen ipmi_ek_display_shelf_power_distribution_record(
3163c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header *record)
3164c18ec02fSPetter Reinholdtsen {
3165c18ec02fSPetter Reinholdtsen 	int offset = START_DATA_OFFSET;
3166b37b9149SZdenek Styblik 	unsigned char i;
3167b37b9149SZdenek Styblik 	unsigned char j;
3168c18ec02fSPetter Reinholdtsen 	unsigned char feeds = 0;
3169c18ec02fSPetter Reinholdtsen 
3170c18ec02fSPetter Reinholdtsen 	feeds = record->data[offset++];
3171c18ec02fSPetter Reinholdtsen 	printf("   Number of Power Feeds: 0x%02x\n", feeds);
3172c18ec02fSPetter Reinholdtsen 	for (i = 0; i < feeds; i++) {
3173c18ec02fSPetter Reinholdtsen 		unsigned char entries;
3174c18ec02fSPetter Reinholdtsen 		unsigned long max_ext = 0;
3175c18ec02fSPetter Reinholdtsen 		unsigned long max_int = 0;
3176b37b9149SZdenek Styblik 		max_ext = record->data[offset+0]
3177b37b9149SZdenek Styblik 			| (record->data[offset+1] << 8);
3178b37b9149SZdenek Styblik 		printf("   Max External Available Current: %ld Amps\n",
3179b37b9149SZdenek Styblik 				(max_ext * 10));
3180c18ec02fSPetter Reinholdtsen 		offset += 2;
3181b37b9149SZdenek Styblik 		max_int = record->data[offset+0]
3182b37b9149SZdenek Styblik 			| (record->data[offset+1] << 8);
3183b37b9149SZdenek Styblik 		printf("   Max Internal Current:\t   %ld Amps\n",
3184b37b9149SZdenek Styblik 				(max_int * 10));
3185c18ec02fSPetter Reinholdtsen 		offset += 2;
3186c18ec02fSPetter Reinholdtsen 		printf("   Min Expected Operating Voltage: %d Volts\n",
3187c18ec02fSPetter Reinholdtsen 				(record->data[offset++] / 2));
3188c18ec02fSPetter Reinholdtsen 		entries = record->data[offset++];
3189c18ec02fSPetter Reinholdtsen 		printf("   Feed to FRU count: 0x%02x\n", entries);
3190c18ec02fSPetter Reinholdtsen 		for (j = 0; j < entries; j++) {
3191c18ec02fSPetter Reinholdtsen 			printf("\tHW: 0x%02x", record->data[offset++]);
3192c18ec02fSPetter Reinholdtsen 			printf("\tFRU ID: 0x%02x\n", record->data[offset++]);
3193c18ec02fSPetter Reinholdtsen 		}
3194c18ec02fSPetter Reinholdtsen 	}
3195c18ec02fSPetter Reinholdtsen }
3196c18ec02fSPetter Reinholdtsen 
3197c18ec02fSPetter Reinholdtsen /**************************************************************************
3198c18ec02fSPetter Reinholdtsen *
3199c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_shelf_activation_record
3200c18ec02fSPetter Reinholdtsen *
3201c18ec02fSPetter Reinholdtsen * Description: this function displays shelf activation record.
3202c18ec02fSPetter Reinholdtsen *
3203c18ec02fSPetter Reinholdtsen * Restriction: Reference: PICMG 3.0 Specification Table 3-73
3204c18ec02fSPetter Reinholdtsen *
3205c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3206c18ec02fSPetter Reinholdtsen *
3207c18ec02fSPetter Reinholdtsen * Output: None
3208c18ec02fSPetter Reinholdtsen *
3209c18ec02fSPetter Reinholdtsen * Global: None
3210c18ec02fSPetter Reinholdtsen *
3211c18ec02fSPetter Reinholdtsen * Return: None
3212c18ec02fSPetter Reinholdtsen *
3213c18ec02fSPetter Reinholdtsen ***************************************************************************/
3214c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_shelf_activation_record(struct ipmi_ek_multi_header * record)3215b37b9149SZdenek Styblik ipmi_ek_display_shelf_activation_record(struct ipmi_ek_multi_header *record)
3216c18ec02fSPetter Reinholdtsen {
3217c18ec02fSPetter Reinholdtsen 	unsigned char count = 0;
3218c18ec02fSPetter Reinholdtsen 	int offset = START_DATA_OFFSET;
3219c18ec02fSPetter Reinholdtsen 
3220c18ec02fSPetter Reinholdtsen 	printf("   Allowance for FRU Act Readiness: 0x%02x\n",
3221c18ec02fSPetter Reinholdtsen 			record->data[offset++]);
3222c18ec02fSPetter Reinholdtsen 	count = record->data[offset++];
3223c18ec02fSPetter Reinholdtsen 	printf("   FRU activation and Power Desc Cnt: 0x%02x\n", count);
3224c18ec02fSPetter Reinholdtsen 	while (count > 0) {
3225c18ec02fSPetter Reinholdtsen 		printf("   FRU activation and Power descriptor:\n");
3226b37b9149SZdenek Styblik 		printf("\tHardware Address:\t\t0x%02x\n",
3227b37b9149SZdenek Styblik 				record->data[offset++]);
3228b37b9149SZdenek Styblik 		printf("\tFRU Device ID:\t\t\t0x%02x\n",
3229b37b9149SZdenek Styblik 				record->data[offset++]);
3230c18ec02fSPetter Reinholdtsen 		printf("\tMax FRU Power Capability:\t0x%04x Watts\n",
3231b37b9149SZdenek Styblik 				(record->data[offset+0]
3232b37b9149SZdenek Styblik 				 | (record->data[offset+1]<<8)));
3233c18ec02fSPetter Reinholdtsen 		offset += 2;
3234b37b9149SZdenek Styblik 		printf("\tConfiguration parameter:\t0x%02x\n",
3235b37b9149SZdenek Styblik 				record->data[offset++]);
3236c18ec02fSPetter Reinholdtsen 		count --;
3237c18ec02fSPetter Reinholdtsen 	}
3238c18ec02fSPetter Reinholdtsen }
3239c18ec02fSPetter Reinholdtsen 
3240c18ec02fSPetter Reinholdtsen /**************************************************************************
3241c18ec02fSPetter Reinholdtsen *
3242c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_shelf_ip_connection_record
3243c18ec02fSPetter Reinholdtsen *
3244c18ec02fSPetter Reinholdtsen * Description: this function displays shelf ip connection record.
3245c18ec02fSPetter Reinholdtsen *
3246c18ec02fSPetter Reinholdtsen * Restriction: Fix me: Don't test yet
3247c18ec02fSPetter Reinholdtsen *               Reference: PICMG 3.0 Specification Table 3-31
3248c18ec02fSPetter Reinholdtsen *
3249c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3250c18ec02fSPetter Reinholdtsen *
3251c18ec02fSPetter Reinholdtsen * Output: None
3252c18ec02fSPetter Reinholdtsen *
3253c18ec02fSPetter Reinholdtsen * Global: None
3254c18ec02fSPetter Reinholdtsen *
3255c18ec02fSPetter Reinholdtsen * Return: None
3256c18ec02fSPetter Reinholdtsen *
3257c18ec02fSPetter Reinholdtsen ***************************************************************************/
3258c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_shelf_ip_connection_record(struct ipmi_ek_multi_header * record)3259b37b9149SZdenek Styblik ipmi_ek_display_shelf_ip_connection_record(struct ipmi_ek_multi_header *record)
3260c18ec02fSPetter Reinholdtsen {
3261c18ec02fSPetter Reinholdtsen 	int ioffset = START_DATA_OFFSET;
3262c18ec02fSPetter Reinholdtsen 	if (ioffset > record->header.len) {
3263c18ec02fSPetter Reinholdtsen 		printf("   Shelf Manager IP Address: %d.%d.%d.%d\n",
3264b37b9149SZdenek Styblik 				record->data[ioffset+0],
3265b37b9149SZdenek Styblik 				record->data[ioffset+1],
3266b37b9149SZdenek Styblik 				record->data[ioffset+2],
3267b37b9149SZdenek Styblik 				record->data[ioffset+3]);
3268c18ec02fSPetter Reinholdtsen 		ioffset += 4;
3269c18ec02fSPetter Reinholdtsen 	}
3270c18ec02fSPetter Reinholdtsen 	if (ioffset > record->header.len) {
3271c18ec02fSPetter Reinholdtsen 		printf("   Default Gateway Address: %d.%d.%d.%d\n",
3272b37b9149SZdenek Styblik 				record->data[ioffset+0],
3273b37b9149SZdenek Styblik 				record->data[ioffset+1],
3274b37b9149SZdenek Styblik 				record->data[ioffset+2],
3275b37b9149SZdenek Styblik 				record->data[ioffset+3]);
3276c18ec02fSPetter Reinholdtsen 		ioffset += 4;
3277c18ec02fSPetter Reinholdtsen 	}
3278c18ec02fSPetter Reinholdtsen 	if (ioffset > record->header.len) {
3279c18ec02fSPetter Reinholdtsen 		printf("   Subnet Mask: %d.%d.%d.%d\n",
3280b37b9149SZdenek Styblik 				record->data[ioffset+0],
3281b37b9149SZdenek Styblik 				record->data[ioffset+1],
3282b37b9149SZdenek Styblik 				record->data[ioffset+2],
3283b37b9149SZdenek Styblik 				record->data[ioffset+3]);
3284c18ec02fSPetter Reinholdtsen 		ioffset += 4;
3285c18ec02fSPetter Reinholdtsen 	}
3286c18ec02fSPetter Reinholdtsen }
3287c18ec02fSPetter Reinholdtsen 
3288c18ec02fSPetter Reinholdtsen /**************************************************************************
3289c18ec02fSPetter Reinholdtsen *
3290c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_shelf_fan_geography_record
3291c18ec02fSPetter Reinholdtsen *
3292c18ec02fSPetter Reinholdtsen * Description: this function displays shelf fan geography record.
3293c18ec02fSPetter Reinholdtsen *
3294c18ec02fSPetter Reinholdtsen * Restriction: Fix me: Don't test yet
3295c18ec02fSPetter Reinholdtsen *               Reference: PICMG 3.0 Specification Table 3-75
3296c18ec02fSPetter Reinholdtsen *
3297c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3298c18ec02fSPetter Reinholdtsen *
3299c18ec02fSPetter Reinholdtsen * Output: None
3300c18ec02fSPetter Reinholdtsen *
3301c18ec02fSPetter Reinholdtsen * Global: None
3302c18ec02fSPetter Reinholdtsen *
3303c18ec02fSPetter Reinholdtsen * Return: None
3304c18ec02fSPetter Reinholdtsen *
3305c18ec02fSPetter Reinholdtsen ***************************************************************************/
3306c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_shelf_fan_geography_record(struct ipmi_ek_multi_header * record)3307b37b9149SZdenek Styblik ipmi_ek_display_shelf_fan_geography_record(struct ipmi_ek_multi_header *record)
3308c18ec02fSPetter Reinholdtsen {
3309c18ec02fSPetter Reinholdtsen 	int ioffset = START_DATA_OFFSET;
3310c18ec02fSPetter Reinholdtsen 	unsigned char fan_count = 0;
3311c18ec02fSPetter Reinholdtsen 
3312c18ec02fSPetter Reinholdtsen 	fan_count = record->data[ioffset];
3313c18ec02fSPetter Reinholdtsen 	ioffset++;
3314c18ec02fSPetter Reinholdtsen 	printf("   Fan-to-FRU Entry Count: 0x%02x\n", fan_count);
3315c18ec02fSPetter Reinholdtsen 	while ((fan_count > 0) && (ioffset <= record->header.len)) {
3316c18ec02fSPetter Reinholdtsen 		printf("   Fan-to-FRU Mapping Entry: {%2x%2x%2x%2x}\n",
3317b37b9149SZdenek Styblik 				record->data[ioffset],
3318b37b9149SZdenek Styblik 				record->data[ioffset+1],
3319b37b9149SZdenek Styblik 				record->data[ioffset+2],
3320b37b9149SZdenek Styblik 				record->data[ioffset+3]);
3321b37b9149SZdenek Styblik 		printf("      Hardware Address:   0x%02x\n",
3322b37b9149SZdenek Styblik 				record->data[ioffset++]);
3323b37b9149SZdenek Styblik 		printf("      FRU device ID:   0x%02x\n",
3324b37b9149SZdenek Styblik 				record->data[ioffset++]);
3325b37b9149SZdenek Styblik 		printf("      Site Number:   0x%02x\n",
3326b37b9149SZdenek Styblik 				record->data[ioffset++]);
3327b37b9149SZdenek Styblik 		printf("      Site Type:   0x%02x\n",
3328b37b9149SZdenek Styblik 				record->data[ioffset++]);
3329c18ec02fSPetter Reinholdtsen 		fan_count --;
3330c18ec02fSPetter Reinholdtsen 	}
3331c18ec02fSPetter Reinholdtsen }
3332c18ec02fSPetter Reinholdtsen 
3333c18ec02fSPetter Reinholdtsen /**************************************************************************
3334c18ec02fSPetter Reinholdtsen *
3335c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_board_p2p_record
3336c18ec02fSPetter Reinholdtsen *
3337c18ec02fSPetter Reinholdtsen * Description: this function displays board pont-to-point record.
3338c18ec02fSPetter Reinholdtsen *
3339c18ec02fSPetter Reinholdtsen * Restriction: Reference: PICMG 3.0 Specification Table 3-44
3340c18ec02fSPetter Reinholdtsen *
3341c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3342c18ec02fSPetter Reinholdtsen *
3343c18ec02fSPetter Reinholdtsen * Output: None
3344c18ec02fSPetter Reinholdtsen *
3345c18ec02fSPetter Reinholdtsen * Global: None
3346c18ec02fSPetter Reinholdtsen *
3347c18ec02fSPetter Reinholdtsen * Return: None
3348c18ec02fSPetter Reinholdtsen *
3349c18ec02fSPetter Reinholdtsen ***************************************************************************/
3350c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_board_p2p_record(struct ipmi_ek_multi_header * record)3351c18ec02fSPetter Reinholdtsen ipmi_ek_display_board_p2p_record(struct ipmi_ek_multi_header *record)
3352c18ec02fSPetter Reinholdtsen {
3353c18ec02fSPetter Reinholdtsen 	unsigned char guid_count;
3354c18ec02fSPetter Reinholdtsen 	int offset = START_DATA_OFFSET;
3355c18ec02fSPetter Reinholdtsen 	int i = 0;
3356c18ec02fSPetter Reinholdtsen 
3357c18ec02fSPetter Reinholdtsen 	guid_count = record->data[offset++];
3358c18ec02fSPetter Reinholdtsen 	printf("   GUID count: %2d\n", guid_count);
3359c18ec02fSPetter Reinholdtsen 	for (i = 0 ; i < guid_count; i++) {
3360c18ec02fSPetter Reinholdtsen 		int j;
3361c18ec02fSPetter Reinholdtsen 		printf("\tGUID: ");
3362c18ec02fSPetter Reinholdtsen 		for (j = 0; j < sizeof(struct fru_picmgext_guid); j++) {
3363c18ec02fSPetter Reinholdtsen 			printf("%02x", record->data[offset+j]);
3364c18ec02fSPetter Reinholdtsen 		}
3365c18ec02fSPetter Reinholdtsen 		printf("\n");
3366c18ec02fSPetter Reinholdtsen 		offset += sizeof(struct fru_picmgext_guid);
3367c18ec02fSPetter Reinholdtsen 	}
3368c18ec02fSPetter Reinholdtsen 	for (offset;
3369c18ec02fSPetter Reinholdtsen 			offset < record->header.len;
3370b37b9149SZdenek Styblik 			offset += sizeof(struct fru_picmgext_link_desc)) {
3371c18ec02fSPetter Reinholdtsen 		/* to solve little endian/big endian problem */
3372c18ec02fSPetter Reinholdtsen 		unsigned long data;
3373c18ec02fSPetter Reinholdtsen 		struct fru_picmgext_link_desc * d;
3374b37b9149SZdenek Styblik 		data = (record->data[offset+0])
3375b37b9149SZdenek Styblik 			| (record->data[offset+1] << 8)\
3376c18ec02fSPetter Reinholdtsen 			| (record->data[offset+2] << 16)\
3377c18ec02fSPetter Reinholdtsen 			| (record->data[offset+3] << 24);
3378c18ec02fSPetter Reinholdtsen 		d = (struct fru_picmgext_link_desc *)&data;
3379c18ec02fSPetter Reinholdtsen 
3380c18ec02fSPetter Reinholdtsen 		printf("   Link Descriptor\n");
3381c18ec02fSPetter Reinholdtsen 		printf("\tLink Grouping ID:\t0x%02x\n", d->grouping);
3382c18ec02fSPetter Reinholdtsen 		printf("\tLink Type Extension:\t0x%02x - ", d->ext);
3383c18ec02fSPetter Reinholdtsen 		if (d->type == FRU_PICMGEXT_LINK_TYPE_BASE) {
3384c18ec02fSPetter Reinholdtsen 			switch (d->ext) {
3385c18ec02fSPetter Reinholdtsen 			case 0:
3386c18ec02fSPetter Reinholdtsen 				printf("10/100/1000BASE-T Link (four-pair)\n");
3387c18ec02fSPetter Reinholdtsen 				break;
3388c18ec02fSPetter Reinholdtsen 			case 1:
3389c18ec02fSPetter Reinholdtsen 				printf("ShMC Cross-connect (two-pair)\n");
3390c18ec02fSPetter Reinholdtsen 				break;
3391c18ec02fSPetter Reinholdtsen 			default:
3392c18ec02fSPetter Reinholdtsen 				printf("Unknwon\n");
3393c18ec02fSPetter Reinholdtsen 				break;
3394c18ec02fSPetter Reinholdtsen 			}
3395b37b9149SZdenek Styblik 		} else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET) {
3396c18ec02fSPetter Reinholdtsen 			switch (d->ext) {
3397c18ec02fSPetter Reinholdtsen 			case 0:
3398c18ec02fSPetter Reinholdtsen 				printf("Fixed 1000Base-BX\n");
3399c18ec02fSPetter Reinholdtsen 				break;
3400c18ec02fSPetter Reinholdtsen 			case 1:
3401c18ec02fSPetter Reinholdtsen 				printf("Fixed 10GBASE-BX4 [XAUI]\n");
3402c18ec02fSPetter Reinholdtsen 				break;
3403c18ec02fSPetter Reinholdtsen 			case 2:
3404c18ec02fSPetter Reinholdtsen 				printf("FC-PI\n");
3405c18ec02fSPetter Reinholdtsen 				break;
3406c18ec02fSPetter Reinholdtsen 			default:
3407c18ec02fSPetter Reinholdtsen 				printf("Unknwon\n");
3408c18ec02fSPetter Reinholdtsen 				break;
3409c18ec02fSPetter Reinholdtsen 			}
3410b37b9149SZdenek Styblik 		} else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND) {
3411b37b9149SZdenek Styblik 			printf("Unknwon\n");
3412b37b9149SZdenek Styblik 		} else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR) {
3413b37b9149SZdenek Styblik 			printf("Unknwon\n");
3414b37b9149SZdenek Styblik 		} else if (d->type == FRU_PICMGEXT_LINK_TYPE_PCIE) {
3415b37b9149SZdenek Styblik 			printf("Unknwon\n");
3416b37b9149SZdenek Styblik 		} else {
3417c18ec02fSPetter Reinholdtsen 			printf("Unknwon\n");
3418c18ec02fSPetter Reinholdtsen 		}
3419c18ec02fSPetter Reinholdtsen 		printf("\tLink Type:\t\t0x%02x - ", d->type);
3420c18ec02fSPetter Reinholdtsen 		if (d->type == 0 || d->type == 0xff) {
3421c18ec02fSPetter Reinholdtsen 			printf("Reserved\n");
3422b37b9149SZdenek Styblik 		} else if (d->type >= 0x06 && d->type <= 0xef) {
3423c18ec02fSPetter Reinholdtsen 			printf("Reserved\n");
3424b37b9149SZdenek Styblik 		} else if (d->type >= LOWER_OEM_TYPE && d->type <= UPPER_OEM_TYPE) {
3425c18ec02fSPetter Reinholdtsen 			printf("OEM GUID Definition\n");
3426b37b9149SZdenek Styblik 		} else {
3427c18ec02fSPetter Reinholdtsen 			switch (d->type){
3428c18ec02fSPetter Reinholdtsen 			case FRU_PICMGEXT_LINK_TYPE_BASE:
3429c18ec02fSPetter Reinholdtsen 				printf("PICMG 3.0 Base Interface 10/100/1000\n");
3430c18ec02fSPetter Reinholdtsen 				break;
3431c18ec02fSPetter Reinholdtsen 			case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET:
3432c18ec02fSPetter Reinholdtsen 				printf("PICMG 3.1 Ethernet Fabric Interface\n");
3433c18ec02fSPetter Reinholdtsen 				break;
3434c18ec02fSPetter Reinholdtsen 			case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND:
3435c18ec02fSPetter Reinholdtsen 				printf("PICMG 3.2 Infiniband Fabric Interface\n");
3436c18ec02fSPetter Reinholdtsen 				break;
3437c18ec02fSPetter Reinholdtsen 			case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR:
3438c18ec02fSPetter Reinholdtsen 				printf("PICMG 3.3 Star Fabric Interface\n");
3439c18ec02fSPetter Reinholdtsen 				break;
3440c18ec02fSPetter Reinholdtsen 			case FRU_PICMGEXT_LINK_TYPE_PCIE:
3441c18ec02fSPetter Reinholdtsen 				printf("PICMG 3.4 PCI Express Fabric Interface\n");
3442c18ec02fSPetter Reinholdtsen 				break;
3443c18ec02fSPetter Reinholdtsen 			default:
3444c18ec02fSPetter Reinholdtsen 				printf("Invalid\n");
3445c18ec02fSPetter Reinholdtsen 				break;
3446c18ec02fSPetter Reinholdtsen 			}
3447c18ec02fSPetter Reinholdtsen 		}
3448c18ec02fSPetter Reinholdtsen 		printf("\tLink Designator: \n");
3449c18ec02fSPetter Reinholdtsen 		printf("\t   Port 0 Flag:   %s\n",
3450c18ec02fSPetter Reinholdtsen 				(d->desig_port & 0x01) ? "enable" : "disable");
3451c18ec02fSPetter Reinholdtsen 		printf("\t   Port 1 Flag:   %s\n",
3452c18ec02fSPetter Reinholdtsen 				(d->desig_port & 0x02) ? "enable" : "disable");
3453c18ec02fSPetter Reinholdtsen 		printf("\t   Port 2 Flag:   %s\n",
3454c18ec02fSPetter Reinholdtsen 				(d->desig_port & 0x04) ? "enable" : "disable");
3455c18ec02fSPetter Reinholdtsen 		printf("\t   Port 3 Flag:   %s\n",
3456c18ec02fSPetter Reinholdtsen 				(d->desig_port & 0x08) ? "enable" : "disable");
3457c18ec02fSPetter Reinholdtsen 		printf("\t   Interface:    0x%02x - ", d->desig_if);
3458c18ec02fSPetter Reinholdtsen 		switch (d->desig_if) {
3459c18ec02fSPetter Reinholdtsen 		case FRU_PICMGEXT_DESIGN_IF_BASE:
3460c18ec02fSPetter Reinholdtsen 			printf("Base Interface\n");
3461c18ec02fSPetter Reinholdtsen 			break;
3462c18ec02fSPetter Reinholdtsen 		case FRU_PICMGEXT_DESIGN_IF_FABRIC:
3463c18ec02fSPetter Reinholdtsen 			printf("Fabric Interface\n");
3464c18ec02fSPetter Reinholdtsen 			break;
3465c18ec02fSPetter Reinholdtsen 		case FRU_PICMGEXT_DESIGN_IF_UPDATE_CHANNEL:
3466c18ec02fSPetter Reinholdtsen 			printf("Update Channel\n");
3467c18ec02fSPetter Reinholdtsen 			break;
3468c18ec02fSPetter Reinholdtsen 		case FRU_PICMGEXT_DESIGN_IF_RESERVED:
3469c18ec02fSPetter Reinholdtsen 			printf("Reserved\n");
3470c18ec02fSPetter Reinholdtsen 			break;
3471c18ec02fSPetter Reinholdtsen 		default:
3472c18ec02fSPetter Reinholdtsen 			printf("Invalid");
3473c18ec02fSPetter Reinholdtsen 			break;
3474c18ec02fSPetter Reinholdtsen 		}
3475b37b9149SZdenek Styblik 		printf("\t   Channel Number:    0x%02x\n",
3476b37b9149SZdenek Styblik 				d->desig_channel);
3477c18ec02fSPetter Reinholdtsen 	}
3478c18ec02fSPetter Reinholdtsen }
3479c18ec02fSPetter Reinholdtsen 
3480c18ec02fSPetter Reinholdtsen /**************************************************************************
3481c18ec02fSPetter Reinholdtsen *
3482c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_radial_ipmb0_record
3483c18ec02fSPetter Reinholdtsen *
3484c18ec02fSPetter Reinholdtsen * Description: this function displays radial IPMB-0 record.
3485c18ec02fSPetter Reinholdtsen *
3486c18ec02fSPetter Reinholdtsen * Restriction: Fix me: Don't test yet
3487c18ec02fSPetter Reinholdtsen *
3488c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3489c18ec02fSPetter Reinholdtsen *
3490c18ec02fSPetter Reinholdtsen * Output: None
3491c18ec02fSPetter Reinholdtsen *
3492c18ec02fSPetter Reinholdtsen * Global: None
3493c18ec02fSPetter Reinholdtsen *
3494c18ec02fSPetter Reinholdtsen * Return: None
3495c18ec02fSPetter Reinholdtsen *
3496c18ec02fSPetter Reinholdtsen ***************************************************************************/
3497c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_radial_ipmb0_record(struct ipmi_ek_multi_header * record)3498c18ec02fSPetter Reinholdtsen ipmi_ek_display_radial_ipmb0_record(struct ipmi_ek_multi_header *record)
3499c18ec02fSPetter Reinholdtsen {
3500c18ec02fSPetter Reinholdtsen #define SIZE_OF_CONNECTOR_DEFINER  3; /*bytes*/
3501b37b9149SZdenek Styblik 	int offset = START_DATA_OFFSET;
3502c18ec02fSPetter Reinholdtsen 	/* Ref: PICMG 3.0 Specification Revision 2.0, Table 3-59 */
3503c18ec02fSPetter Reinholdtsen 	printf("   IPMB-0 Connector Definer: ");
3504c18ec02fSPetter Reinholdtsen #ifndef WORDS_BIGENDIAN
3505c18ec02fSPetter Reinholdtsen 	printf("%02x %02x %02x h\n", record->data[offset],
3506c18ec02fSPetter Reinholdtsen 			record->data[offset+1], record->data[offset+2]);
3507c18ec02fSPetter Reinholdtsen #else
3508c18ec02fSPetter Reinholdtsen 	printf("%02x %02x %02x h\n", record->data[offset+2],
3509c18ec02fSPetter Reinholdtsen 			record->data[offset+1], record->data[offset]);
3510c18ec02fSPetter Reinholdtsen #endif
3511c18ec02fSPetter Reinholdtsen 	/* 3 bytes of connector definer was used */
3512c18ec02fSPetter Reinholdtsen 	offset += SIZE_OF_CONNECTOR_DEFINER;
3513c18ec02fSPetter Reinholdtsen 	printf("   IPMB-0 Connector version ID: ");
3514c18ec02fSPetter Reinholdtsen #ifndef WORDS_BIGENDIAN
3515b37b9149SZdenek Styblik 	printf("%02x %02x h\n", record->data[offset],
3516b37b9149SZdenek Styblik 			record->data[offset+1]);
3517c18ec02fSPetter Reinholdtsen #else
3518b37b9149SZdenek Styblik 	printf("%02x %02x h\n", record->data[offset+1],
3519b37b9149SZdenek Styblik 			record->data[offset]);
3520c18ec02fSPetter Reinholdtsen #endif
3521c18ec02fSPetter Reinholdtsen 	offset += 2;
3522b37b9149SZdenek Styblik 	printf("   IPMB-0 Hub Descriptor Count: 0x%02x",
3523b37b9149SZdenek Styblik 			record->data[offset++]);
3524b37b9149SZdenek Styblik 	if (record->data[offset] < 1) {
3525b37b9149SZdenek Styblik 		return;
3526b37b9149SZdenek Styblik 	}
3527c18ec02fSPetter Reinholdtsen 	for (offset; offset < record->header.len;) {
3528c18ec02fSPetter Reinholdtsen 		unsigned char entry_count = 0;
3529c18ec02fSPetter Reinholdtsen 		printf("   IPMB-0 Hub Descriptor\n");
3530b37b9149SZdenek Styblik 		printf("\tHardware Address: 0x%02x\n",
3531b37b9149SZdenek Styblik 				record->data[offset++]);
3532c18ec02fSPetter Reinholdtsen 		printf("\tHub Info {0x%02x}: ", record->data[offset]);
3533b37b9149SZdenek Styblik 		/* Bit mask specified in Table 3-59
3534b37b9149SZdenek Styblik 		 * of PICMG 3.0 Specification
3535b37b9149SZdenek Styblik 		 */
3536c18ec02fSPetter Reinholdtsen 		if ((record->data[offset] & 0x01) == 0x01) {
3537c18ec02fSPetter Reinholdtsen 			printf("IPMB-A only\n");
3538b37b9149SZdenek Styblik 		} else if ((record->data[offset] & 0x02) == 0x02) {
3539c18ec02fSPetter Reinholdtsen 			printf("IPMB-B only\n");
3540b37b9149SZdenek Styblik 		} else if ((record->data[offset] & 0x03) == 0x03) {
3541c18ec02fSPetter Reinholdtsen 			printf("IPMB-A and IPMB-B\n");
3542b37b9149SZdenek Styblik 		} else {
3543c18ec02fSPetter Reinholdtsen 			printf("Reserved.\n");
3544c18ec02fSPetter Reinholdtsen 		}
3545c18ec02fSPetter Reinholdtsen 		offset ++;
3546c18ec02fSPetter Reinholdtsen 		entry_count = record->data[offset++];
3547c18ec02fSPetter Reinholdtsen 		printf("\tAddress Entry count: 0x%02x", entry_count);
3548c18ec02fSPetter Reinholdtsen 		while (entry_count > 0) {
3549b37b9149SZdenek Styblik 			printf("\t   Hardware Address: 0x%02x\n",
3550b37b9149SZdenek Styblik 					record->data[offset++]);
3551b37b9149SZdenek Styblik 			printf("\t   IPMB-0 Link Entry: 0x%02x\n",
3552b37b9149SZdenek Styblik 					record->data[offset++]);
3553c18ec02fSPetter Reinholdtsen 			entry_count --;
3554c18ec02fSPetter Reinholdtsen 		}
3555c18ec02fSPetter Reinholdtsen 	}
3556c18ec02fSPetter Reinholdtsen }
3557c18ec02fSPetter Reinholdtsen 
3558c18ec02fSPetter Reinholdtsen /**************************************************************************
3559c18ec02fSPetter Reinholdtsen *
3560c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_amc_current_record
3561c18ec02fSPetter Reinholdtsen *
3562c18ec02fSPetter Reinholdtsen * Description: this function displays AMC current record.
3563c18ec02fSPetter Reinholdtsen *
3564c18ec02fSPetter Reinholdtsen * Restriction: None
3565c18ec02fSPetter Reinholdtsen *
3566c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3567c18ec02fSPetter Reinholdtsen *
3568c18ec02fSPetter Reinholdtsen * Output: None
3569c18ec02fSPetter Reinholdtsen *
3570c18ec02fSPetter Reinholdtsen * Global: None
3571c18ec02fSPetter Reinholdtsen *
3572c18ec02fSPetter Reinholdtsen * Return: None
3573c18ec02fSPetter Reinholdtsen *
3574c18ec02fSPetter Reinholdtsen ***************************************************************************/
3575c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_amc_current_record(struct ipmi_ek_multi_header * record)3576c18ec02fSPetter Reinholdtsen ipmi_ek_display_amc_current_record(struct ipmi_ek_multi_header *record)
3577c18ec02fSPetter Reinholdtsen {
3578c18ec02fSPetter Reinholdtsen 	unsigned char current;
3579c18ec02fSPetter Reinholdtsen 	current = record->data[START_DATA_OFFSET];
3580c18ec02fSPetter Reinholdtsen 	printf("   Current draw: %.1f A @ 12V => %.2f Watt\n",
3581b37b9149SZdenek Styblik 			(float)current / 10.0,
3582b37b9149SZdenek Styblik 			((float)current / 10.0) * 12.0);
3583c18ec02fSPetter Reinholdtsen 	printf("\n");
3584c18ec02fSPetter Reinholdtsen }
3585c18ec02fSPetter Reinholdtsen 
3586c18ec02fSPetter Reinholdtsen /**************************************************************************
3587c18ec02fSPetter Reinholdtsen *
3588c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_amc_activation_record
3589c18ec02fSPetter Reinholdtsen *
3590c18ec02fSPetter Reinholdtsen * Description: this function displays carrier activation and current management
3591c18ec02fSPetter Reinholdtsen *             record.
3592c18ec02fSPetter Reinholdtsen *
3593c18ec02fSPetter Reinholdtsen * Restriction: Reference: AMC.0 Specification Table 3-11 and Table 3-12
3594c18ec02fSPetter Reinholdtsen *
3595c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3596c18ec02fSPetter Reinholdtsen *
3597c18ec02fSPetter Reinholdtsen * Output: None
3598c18ec02fSPetter Reinholdtsen *
3599c18ec02fSPetter Reinholdtsen * Global: None
3600c18ec02fSPetter Reinholdtsen *
3601c18ec02fSPetter Reinholdtsen * Return: None
3602c18ec02fSPetter Reinholdtsen *
3603c18ec02fSPetter Reinholdtsen ***************************************************************************/
3604c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_amc_activation_record(struct ipmi_ek_multi_header * record)3605c18ec02fSPetter Reinholdtsen ipmi_ek_display_amc_activation_record(struct ipmi_ek_multi_header *record)
3606c18ec02fSPetter Reinholdtsen {
3607c18ec02fSPetter Reinholdtsen 	uint16_t max_current;
3608c18ec02fSPetter Reinholdtsen 	int offset = START_DATA_OFFSET;
3609c18ec02fSPetter Reinholdtsen 
3610c18ec02fSPetter Reinholdtsen 	max_current = record->data[offset];
3611c18ec02fSPetter Reinholdtsen 	max_current |= record->data[++offset] << 8;
3612c18ec02fSPetter Reinholdtsen 	printf("   Maximum Internal Current(@12V): %.2f A [ %.2f Watt ]\n",
3613c18ec02fSPetter Reinholdtsen 			(float) max_current / 10,
3614c18ec02fSPetter Reinholdtsen 			(float) max_current / 10 * 12);
3615c18ec02fSPetter Reinholdtsen 	printf("   Module Activation Readiness:    %i sec.\n",
3616c18ec02fSPetter Reinholdtsen 			record->data[++offset]);
3617c18ec02fSPetter Reinholdtsen 	printf("   Descriptor Count: %i\n", record->data[++offset]);
3618b37b9149SZdenek Styblik 	for (++offset; (offset < record->header.len); offset += 3) {
3619c18ec02fSPetter Reinholdtsen 		struct fru_picmgext_activation_record *a =
3620c18ec02fSPetter Reinholdtsen 			(struct fru_picmgext_activation_record *)&record->data[offset];
3621c18ec02fSPetter Reinholdtsen 		printf("\tIPMB-Address:\t\t0x%x\n", a->ibmb_addr);
3622b37b9149SZdenek Styblik 		printf("\tMax. Module Current:\t%.2f A\n",
3623b37b9149SZdenek Styblik 				(float)a->max_module_curr / 10);
3624c18ec02fSPetter Reinholdtsen 		printf("\n");
3625c18ec02fSPetter Reinholdtsen 	}
3626c18ec02fSPetter Reinholdtsen }
3627c18ec02fSPetter Reinholdtsen 
3628c18ec02fSPetter Reinholdtsen /**************************************************************************
3629c18ec02fSPetter Reinholdtsen *
3630c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_amc_p2p_record
3631c18ec02fSPetter Reinholdtsen *
3632c18ec02fSPetter Reinholdtsen * Description: this function display amc p2p connectivity record in humain
3633c18ec02fSPetter Reinholdtsen *              readable text format
3634c18ec02fSPetter Reinholdtsen *
3635c18ec02fSPetter Reinholdtsen * Restriction: Reference: AMC.0 Specification Table 3-16
3636c18ec02fSPetter Reinholdtsen *
3637c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3638c18ec02fSPetter Reinholdtsen *
3639c18ec02fSPetter Reinholdtsen * Output: None
3640c18ec02fSPetter Reinholdtsen *
3641c18ec02fSPetter Reinholdtsen * Global: None
3642c18ec02fSPetter Reinholdtsen *
3643c18ec02fSPetter Reinholdtsen * Return: None
3644c18ec02fSPetter Reinholdtsen *
3645c18ec02fSPetter Reinholdtsen ***************************************************************************/
3646c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_amc_p2p_record(struct ipmi_ek_multi_header * record)3647c18ec02fSPetter Reinholdtsen ipmi_ek_display_amc_p2p_record(struct ipmi_ek_multi_header *record)
3648c18ec02fSPetter Reinholdtsen {
3649c18ec02fSPetter Reinholdtsen 	int index_data = START_DATA_OFFSET;
3650c18ec02fSPetter Reinholdtsen 	int oem_count = 0;
3651c18ec02fSPetter Reinholdtsen 	int ch_count = 0;
3652c18ec02fSPetter Reinholdtsen 	int index=0;
3653c18ec02fSPetter Reinholdtsen 
3654c18ec02fSPetter Reinholdtsen 	oem_count = record->data[index_data++];
3655c18ec02fSPetter Reinholdtsen 	printf("OEM GUID count: %02x\n", oem_count);
3656c18ec02fSPetter Reinholdtsen 	if (oem_count > 0) {
3657c18ec02fSPetter Reinholdtsen 		while (oem_count > 0) {
3658c18ec02fSPetter Reinholdtsen 			printf("OEM GUID: ");
3659c18ec02fSPetter Reinholdtsen 			for (index = 1; index <= SIZE_OF_GUID; index++) {
3660c18ec02fSPetter Reinholdtsen 				printf("%02x", record->data[index_data++]);
3661b37b9149SZdenek Styblik 				/* For a better look, display a "-" character
3662b37b9149SZdenek Styblik 				 * after each 5 bytes of OEM GUID
3663b37b9149SZdenek Styblik 				 */
3664c18ec02fSPetter Reinholdtsen 				if (!(index % 5)) {
3665c18ec02fSPetter Reinholdtsen 					printf("-");
3666c18ec02fSPetter Reinholdtsen 				}
3667c18ec02fSPetter Reinholdtsen 			}
3668c18ec02fSPetter Reinholdtsen 			printf("\n");
3669c18ec02fSPetter Reinholdtsen 			oem_count--;
3670c18ec02fSPetter Reinholdtsen 		}
3671c18ec02fSPetter Reinholdtsen 	}
3672c18ec02fSPetter Reinholdtsen 	if ((record->data[index_data] & AMC_MODULE) == AMC_MODULE) {
3673c18ec02fSPetter Reinholdtsen 		printf("AMC module connection\n");
3674b37b9149SZdenek Styblik 	} else {
3675b37b9149SZdenek Styblik 		printf("On-Carrier Device %02x h\n",
3676b37b9149SZdenek Styblik 				(record->data[index_data] & 0x0f));
3677c18ec02fSPetter Reinholdtsen 	}
3678c18ec02fSPetter Reinholdtsen 	index_data ++;
3679c18ec02fSPetter Reinholdtsen 	ch_count = record->data[index_data++];
3680c18ec02fSPetter Reinholdtsen 	printf("AMC Channel Descriptor count: %02x h\n", ch_count);
3681c18ec02fSPetter Reinholdtsen 
3682c18ec02fSPetter Reinholdtsen 	if (ch_count > 0) {
3683c18ec02fSPetter Reinholdtsen 		for (index = 0; index < ch_count; index++) {
3684c18ec02fSPetter Reinholdtsen 			unsigned int data;
3685c18ec02fSPetter Reinholdtsen 			struct fru_picmgext_amc_channel_desc_record *ch_desc;
3686c18ec02fSPetter Reinholdtsen 			printf("   AMC Channel Descriptor {%02x%02x%02x}\n",
3687b37b9149SZdenek Styblik 					record->data[index_data+2],
3688b37b9149SZdenek Styblik 					record->data[index_data+1],
3689b37b9149SZdenek Styblik 					record->data[index_data]);
3690b37b9149SZdenek Styblik 			data = record->data[index_data]
3691b37b9149SZdenek Styblik 				| (record->data[index_data + 1] << 8)
3692b37b9149SZdenek Styblik 				| (record->data[index_data + 2] << 16);
3693c18ec02fSPetter Reinholdtsen 			ch_desc = (struct fru_picmgext_amc_channel_desc_record *)&data;
3694c18ec02fSPetter Reinholdtsen 			printf("      Lane 0 Port: %d\n", ch_desc->lane0port);
3695c18ec02fSPetter Reinholdtsen 			printf("      Lane 1 Port: %d\n", ch_desc->lane1port);
3696c18ec02fSPetter Reinholdtsen 			printf("      Lane 2 Port: %d\n", ch_desc->lane2port);
3697c18ec02fSPetter Reinholdtsen 			printf("      Lane 3 Port: %d\n\n", ch_desc->lane3port);
3698c18ec02fSPetter Reinholdtsen 			index_data += FRU_PICMGEXT_AMC_CHANNEL_DESC_RECORD_SIZE;
3699c18ec02fSPetter Reinholdtsen 		}
3700c18ec02fSPetter Reinholdtsen 	}
3701c18ec02fSPetter Reinholdtsen 	while (index_data < record->header.len) {
3702b37b9149SZdenek Styblik 		/* Warning: This code doesn't work with gcc version
3703b37b9149SZdenek Styblik 		 * between 4.0 and 4.3
3704b37b9149SZdenek Styblik 		 */
3705c18ec02fSPetter Reinholdtsen 		unsigned int data[2];
3706c18ec02fSPetter Reinholdtsen 		struct fru_picmgext_amc_link_desc_record *link_desc;
3707b37b9149SZdenek Styblik 		data[0] = record->data[index_data]
3708b37b9149SZdenek Styblik 			| (record->data[index_data + 1] << 8)
3709b37b9149SZdenek Styblik 			| (record->data[index_data + 2] << 16)
3710b37b9149SZdenek Styblik 			| (record->data[index_data + 3] << 24);
3711c18ec02fSPetter Reinholdtsen 		data[1] = record->data[index_data + 4];
3712c18ec02fSPetter Reinholdtsen 
3713c18ec02fSPetter Reinholdtsen 		link_desc = (struct fru_picmgext_amc_link_desc_record *)&data[0];
3714c18ec02fSPetter Reinholdtsen 		printf("   AMC Link Descriptor:\n");
3715c18ec02fSPetter Reinholdtsen 		printf("\t- Link Type: %s \n",
3716c18ec02fSPetter Reinholdtsen 				val2str(link_desc->type, ipmi_ekanalyzer_link_type));
3717c18ec02fSPetter Reinholdtsen 		switch (link_desc->type) {
3718c18ec02fSPetter Reinholdtsen 		case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE:
3719c18ec02fSPetter Reinholdtsen 		case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS1:
3720c18ec02fSPetter Reinholdtsen 		case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS2:
3721c18ec02fSPetter Reinholdtsen 			printf("\t- Link Type extension: %s\n",
3722b37b9149SZdenek Styblik 					val2str(link_desc->type_ext,
3723b37b9149SZdenek Styblik 						ipmi_ekanalyzer_extension_PCIE));
3724b37b9149SZdenek Styblik 			printf("\t- Link Group ID: %d\n ",
3725b37b9149SZdenek Styblik 					link_desc->group_id);
3726c18ec02fSPetter Reinholdtsen 			printf("\t- Link Asym. Match: %d - %s\n",
3727c18ec02fSPetter Reinholdtsen 					link_desc->asym_match,
3728b37b9149SZdenek Styblik 					val2str(link_desc->asym_match,
3729b37b9149SZdenek Styblik 						ipmi_ekanalyzer_asym_PCIE));
3730c18ec02fSPetter Reinholdtsen 			break;
3731c18ec02fSPetter Reinholdtsen 		case FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET:
3732c18ec02fSPetter Reinholdtsen 			printf("\t- Link Type extension: %s\n",
3733c18ec02fSPetter Reinholdtsen 					val2str (link_desc->type_ext,
3734c18ec02fSPetter Reinholdtsen 						ipmi_ekanalyzer_extension_ETHERNET));
3735b37b9149SZdenek Styblik 			printf("\t- Link Group ID: %d \n",
3736b37b9149SZdenek Styblik 					link_desc->group_id);
3737c18ec02fSPetter Reinholdtsen 			printf("\t- Link Asym. Match: %d - %s\n",
3738c18ec02fSPetter Reinholdtsen 					link_desc->asym_match,
3739b37b9149SZdenek Styblik 					val2str(link_desc->asym_match,
3740b37b9149SZdenek Styblik 						ipmi_ekanalyzer_asym_PCIE));
3741c18ec02fSPetter Reinholdtsen 			break;
3742c18ec02fSPetter Reinholdtsen 		case FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE:
3743c18ec02fSPetter Reinholdtsen 			printf("\t- Link Type extension: %s\n",
3744c18ec02fSPetter Reinholdtsen 					val2str (link_desc->type_ext,
3745c18ec02fSPetter Reinholdtsen 						ipmi_ekanalyzer_extension_STORAGE));
3746b37b9149SZdenek Styblik 			printf("\t- Link Group ID: %d \n",
3747b37b9149SZdenek Styblik 					link_desc->group_id);
3748c18ec02fSPetter Reinholdtsen 			printf("\t- Link Asym. Match: %d - %s\n",
3749c18ec02fSPetter Reinholdtsen 					link_desc->asym_match,
3750b37b9149SZdenek Styblik 					val2str(link_desc->asym_match,
3751b37b9149SZdenek Styblik 						ipmi_ekanalyzer_asym_STORAGE));
3752c18ec02fSPetter Reinholdtsen 			break;
3753c18ec02fSPetter Reinholdtsen 		default:
3754b37b9149SZdenek Styblik 			printf("\t- Link Type extension: %i (Unknown)\n",
3755b37b9149SZdenek Styblik 					link_desc->type_ext);
3756b37b9149SZdenek Styblik 			printf("\t- Link Group ID: %d \n",
3757b37b9149SZdenek Styblik 					link_desc->group_id);
3758b37b9149SZdenek Styblik 			printf("\t- Link Asym. Match: %i\n",
3759b37b9149SZdenek Styblik 					link_desc->asym_match);
3760c18ec02fSPetter Reinholdtsen 			break;
3761c18ec02fSPetter Reinholdtsen 		}
3762c18ec02fSPetter Reinholdtsen 		printf("\t- AMC Link Designator:\n");
3763c18ec02fSPetter Reinholdtsen 		printf("\t    Channel ID: %i\n", link_desc->channel_id);
3764b37b9149SZdenek Styblik 		printf("\t\t Lane 0: %s\n",
3765b37b9149SZdenek Styblik 				(link_desc->port_flag_0) ? "enable" : "disable");
3766b37b9149SZdenek Styblik 		printf("\t\t Lane 1: %s\n",
3767b37b9149SZdenek Styblik 				(link_desc->port_flag_1) ? "enable" : "disable");
3768b37b9149SZdenek Styblik 		printf("\t\t Lane 2: %s\n",
3769b37b9149SZdenek Styblik 				(link_desc->port_flag_2) ? "enable" : "disable");
3770b37b9149SZdenek Styblik 		printf("\t\t Lane 3: %s\n",
3771b37b9149SZdenek Styblik 				(link_desc->port_flag_3) ? "enable" : "disable");
3772c18ec02fSPetter Reinholdtsen 		index_data += FRU_PICMGEXT_AMC_LINK_DESC_RECORD_SIZE;
3773c18ec02fSPetter Reinholdtsen 	}
3774c18ec02fSPetter Reinholdtsen }
3775c18ec02fSPetter Reinholdtsen 
3776c18ec02fSPetter Reinholdtsen /**************************************************************************
3777c18ec02fSPetter Reinholdtsen *
3778c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_amc_carrier_info_record
3779c18ec02fSPetter Reinholdtsen *
3780c18ec02fSPetter Reinholdtsen * Description: this function displays Carrier information table.
3781c18ec02fSPetter Reinholdtsen *
3782c18ec02fSPetter Reinholdtsen * Restriction: Reference: AMC.0 Specification Table 3-3
3783c18ec02fSPetter Reinholdtsen *
3784c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3785c18ec02fSPetter Reinholdtsen *
3786c18ec02fSPetter Reinholdtsen * Output: None
3787c18ec02fSPetter Reinholdtsen *
3788c18ec02fSPetter Reinholdtsen * Global: START_DATA_OFFSET
3789c18ec02fSPetter Reinholdtsen *
3790c18ec02fSPetter Reinholdtsen * Return: None
3791c18ec02fSPetter Reinholdtsen *
3792c18ec02fSPetter Reinholdtsen ***************************************************************************/
3793c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_amc_carrier_info_record(struct ipmi_ek_multi_header * record)3794c18ec02fSPetter Reinholdtsen ipmi_ek_display_amc_carrier_info_record(struct ipmi_ek_multi_header *record)
3795c18ec02fSPetter Reinholdtsen {
3796c18ec02fSPetter Reinholdtsen 	unsigned char extVersion;
3797c18ec02fSPetter Reinholdtsen 	unsigned char siteCount;
3798c18ec02fSPetter Reinholdtsen 	int offset = START_DATA_OFFSET;
3799c18ec02fSPetter Reinholdtsen 
3800c18ec02fSPetter Reinholdtsen 	extVersion = record->data[offset++];
3801c18ec02fSPetter Reinholdtsen 	siteCount  = record->data[offset++];
3802b37b9149SZdenek Styblik 	printf("   AMC.0 extension version: R%d.%d\n",
3803b37b9149SZdenek Styblik 			(extVersion >> 0) & 0x0F,
3804c18ec02fSPetter Reinholdtsen 			(extVersion >> 4) & 0x0F);
3805c18ec02fSPetter Reinholdtsen 	printf("   Carrier Sie Number Count: %d\n", siteCount);
3806c18ec02fSPetter Reinholdtsen 	while (siteCount > 0) {
3807c18ec02fSPetter Reinholdtsen 		printf("\tSite ID (%d): %s \n", record->data[offset],
3808c18ec02fSPetter Reinholdtsen 				val2str(record->data[offset], ipmi_ekanalyzer_module_type));
3809c18ec02fSPetter Reinholdtsen 		offset++;
3810c18ec02fSPetter Reinholdtsen 		siteCount--;
3811c18ec02fSPetter Reinholdtsen 	}
3812c18ec02fSPetter Reinholdtsen 	printf("\n");
3813c18ec02fSPetter Reinholdtsen }
3814c18ec02fSPetter Reinholdtsen 
3815c18ec02fSPetter Reinholdtsen /**************************************************************************
3816c18ec02fSPetter Reinholdtsen *
3817c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_clock_carrier_p2p_record
3818c18ec02fSPetter Reinholdtsen *
3819c18ec02fSPetter Reinholdtsen * Description: this function displays Carrier clock point-to-pont
3820c18ec02fSPetter Reinholdtsen *              connectivity record.
3821c18ec02fSPetter Reinholdtsen *
3822c18ec02fSPetter Reinholdtsen * Restriction: the following code is copy from ipmi_fru.c with modification in
3823c18ec02fSPetter Reinholdtsen *               reference to AMC.0 Specification Table 3-29
3824c18ec02fSPetter Reinholdtsen *
3825c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3826c18ec02fSPetter Reinholdtsen *
3827c18ec02fSPetter Reinholdtsen * Output: None
3828c18ec02fSPetter Reinholdtsen *
3829c18ec02fSPetter Reinholdtsen * Global: None
3830c18ec02fSPetter Reinholdtsen *
3831c18ec02fSPetter Reinholdtsen * Return: None
3832c18ec02fSPetter Reinholdtsen *
3833c18ec02fSPetter Reinholdtsen ***************************************************************************/
3834c18ec02fSPetter Reinholdtsen static void
ipmi_ek_display_clock_carrier_p2p_record(struct ipmi_ek_multi_header * record)3835b37b9149SZdenek Styblik ipmi_ek_display_clock_carrier_p2p_record(struct ipmi_ek_multi_header *record)
3836c18ec02fSPetter Reinholdtsen {
3837c18ec02fSPetter Reinholdtsen 	unsigned char desc_count;
3838b37b9149SZdenek Styblik 	int i;
3839b37b9149SZdenek Styblik 	int j;
3840c18ec02fSPetter Reinholdtsen 	int offset = START_DATA_OFFSET;
3841c18ec02fSPetter Reinholdtsen 
3842c18ec02fSPetter Reinholdtsen 	desc_count = record->data[offset++];
3843c18ec02fSPetter Reinholdtsen 	for(i = 0; i < desc_count; i++) {
3844c18ec02fSPetter Reinholdtsen 		unsigned char resource_id;
3845c18ec02fSPetter Reinholdtsen 		unsigned char channel_count;
3846c18ec02fSPetter Reinholdtsen 
3847c18ec02fSPetter Reinholdtsen 		resource_id = record->data[offset++];
3848c18ec02fSPetter Reinholdtsen 		channel_count = record->data[offset++];
3849c18ec02fSPetter Reinholdtsen 
3850c18ec02fSPetter Reinholdtsen 		printf("   Clock Resource ID: 0x%02x\n", resource_id);
3851c18ec02fSPetter Reinholdtsen 		printf("   Type: ");
3852c18ec02fSPetter Reinholdtsen 		if ((resource_id & 0xC0) >> 6 == 0) {
3853c18ec02fSPetter Reinholdtsen 			printf("On-Carrier-Device\n");
3854b37b9149SZdenek Styblik 		} else if ((resource_id & 0xC0) >> 6 == 1) {
3855c18ec02fSPetter Reinholdtsen 			printf("AMC slot\n");
3856b37b9149SZdenek Styblik 		} else if ((resource_id & 0xC0) >> 6 == 2) {
3857c18ec02fSPetter Reinholdtsen 			printf("Backplane\n");
3858b37b9149SZdenek Styblik 		} else{
3859c18ec02fSPetter Reinholdtsen 			printf("reserved\n");
3860c18ec02fSPetter Reinholdtsen 		}
3861c18ec02fSPetter Reinholdtsen 		printf("   Channel Count: 0x%02x\n", channel_count);
3862c18ec02fSPetter Reinholdtsen 
3863c18ec02fSPetter Reinholdtsen 		for (j = 0; j < channel_count; j++) {
3864b37b9149SZdenek Styblik 			unsigned char loc_channel;
3865b37b9149SZdenek Styblik 			unsigned char rem_channel;
3866b37b9149SZdenek Styblik 			unsigned char rem_resource;
3867c18ec02fSPetter Reinholdtsen 
3868c18ec02fSPetter Reinholdtsen 			loc_channel = record->data[offset++];
3869c18ec02fSPetter Reinholdtsen 			rem_channel = record->data[offset++];
3870c18ec02fSPetter Reinholdtsen 			rem_resource = record->data[offset++];
3871c18ec02fSPetter Reinholdtsen 
3872c18ec02fSPetter Reinholdtsen 			printf("\tCLK-ID: 0x%02x   --->  ", loc_channel);
3873c18ec02fSPetter Reinholdtsen 			printf(" remote CLKID: 0x%02x   ", rem_channel);
3874c18ec02fSPetter Reinholdtsen 			if ((rem_resource & 0xC0) >> 6 == 0) {
3875c18ec02fSPetter Reinholdtsen 				printf("[ Carrier-Dev");
3876b37b9149SZdenek Styblik 			} else if ((rem_resource & 0xC0) >> 6 == 1) {
3877c18ec02fSPetter Reinholdtsen 				printf("[ AMC slot    ");
3878b37b9149SZdenek Styblik 			} else if ((rem_resource & 0xC0) >> 6 == 2) {
3879c18ec02fSPetter Reinholdtsen 				printf("[ Backplane    ");
3880b37b9149SZdenek Styblik 			} else {
3881c18ec02fSPetter Reinholdtsen 				printf("reserved          ");
3882c18ec02fSPetter Reinholdtsen 			}
3883c18ec02fSPetter Reinholdtsen 			printf(" 0x%02x ]\n", rem_resource & 0xF);
3884c18ec02fSPetter Reinholdtsen 		}
3885c18ec02fSPetter Reinholdtsen 	}
3886c18ec02fSPetter Reinholdtsen 	printf("\n");
3887c18ec02fSPetter Reinholdtsen }
3888c18ec02fSPetter Reinholdtsen 
3889c18ec02fSPetter Reinholdtsen /**************************************************************************
3890c18ec02fSPetter Reinholdtsen *
3891c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_display_clock_config_record
3892c18ec02fSPetter Reinholdtsen *
3893c18ec02fSPetter Reinholdtsen * Description: this function displays clock configuration record.
3894c18ec02fSPetter Reinholdtsen *
3895c18ec02fSPetter Reinholdtsen * Restriction: the following codes are copy from ipmi_fru.c with modification
3896c18ec02fSPetter Reinholdtsen *               in reference to AMC.0 Specification Table 3-35 and Table 3-36
3897c18ec02fSPetter Reinholdtsen *
3898c18ec02fSPetter Reinholdtsen * Input: record: a pointer to current record to be displayed
3899c18ec02fSPetter Reinholdtsen *
3900c18ec02fSPetter Reinholdtsen * Output: None
3901c18ec02fSPetter Reinholdtsen *
3902c18ec02fSPetter Reinholdtsen * Global: START_DATA_OFFSET
3903c18ec02fSPetter Reinholdtsen *
3904c18ec02fSPetter Reinholdtsen * Return: None
3905c18ec02fSPetter Reinholdtsen *
3906c18ec02fSPetter Reinholdtsen ***************************************************************************/
3907c18ec02fSPetter Reinholdtsen void
ipmi_ek_display_clock_config_record(struct ipmi_ek_multi_header * record)3908c18ec02fSPetter Reinholdtsen ipmi_ek_display_clock_config_record(struct ipmi_ek_multi_header *record)
3909c18ec02fSPetter Reinholdtsen {
3910b37b9149SZdenek Styblik 	unsigned char resource_id;
3911b37b9149SZdenek Styblik 	unsigned char descr_count;
3912c18ec02fSPetter Reinholdtsen 	int i;
3913c18ec02fSPetter Reinholdtsen 	int offset = START_DATA_OFFSET;
3914c18ec02fSPetter Reinholdtsen 
3915c18ec02fSPetter Reinholdtsen 	resource_id = record->data[offset++];
3916c18ec02fSPetter Reinholdtsen 	descr_count = record->data[offset++];
3917c18ec02fSPetter Reinholdtsen 	printf("   Clock Resource ID: 0x%02x\n", resource_id);
3918c18ec02fSPetter Reinholdtsen 	printf("   Clock Configuration Descriptor Count: 0x%02x\n", descr_count);
3919c18ec02fSPetter Reinholdtsen 
3920c18ec02fSPetter Reinholdtsen 	for (i = 0; i < descr_count; i++) {
3921c18ec02fSPetter Reinholdtsen 		int j = 0;
3922b37b9149SZdenek Styblik 		unsigned char channel_id;
3923b37b9149SZdenek Styblik 		unsigned char control;
3924b37b9149SZdenek Styblik 		unsigned char indirect_cnt;
3925b37b9149SZdenek Styblik 		unsigned char direct_cnt;
3926c18ec02fSPetter Reinholdtsen 
3927c18ec02fSPetter Reinholdtsen 		channel_id = record->data[offset++];
3928c18ec02fSPetter Reinholdtsen 		control = record->data[offset++];
3929c18ec02fSPetter Reinholdtsen 		printf("\tCLK-ID: 0x%02x  -  ", channel_id);
3930c18ec02fSPetter Reinholdtsen 		printf("CTRL 0x%02x [ %12s ]\n", control,
3931c18ec02fSPetter Reinholdtsen 				((control & 0x1) == 0) ? "Carrier IPMC" : "Application");
3932c18ec02fSPetter Reinholdtsen 
3933c18ec02fSPetter Reinholdtsen 		indirect_cnt = record->data[offset++];
3934c18ec02fSPetter Reinholdtsen 		direct_cnt = record->data[offset++];
3935b37b9149SZdenek Styblik 		printf("\t   Count: Indirect 0x%02x   / Direct 0x%02x\n",
3936b37b9149SZdenek Styblik 				indirect_cnt,
3937c18ec02fSPetter Reinholdtsen 				direct_cnt);
3938c18ec02fSPetter Reinholdtsen 
3939c18ec02fSPetter Reinholdtsen 		/* indirect desc */
3940c18ec02fSPetter Reinholdtsen 		for (j = 0; j < indirect_cnt; j++) {
3941c18ec02fSPetter Reinholdtsen 			unsigned char feature;
3942c18ec02fSPetter Reinholdtsen 			unsigned char dep_chn_id;
3943c18ec02fSPetter Reinholdtsen 
3944c18ec02fSPetter Reinholdtsen 			feature = record->data[offset++];
3945c18ec02fSPetter Reinholdtsen 			dep_chn_id = record->data[offset++];
3946b37b9149SZdenek Styblik 			printf("\t\tFeature: 0x%02x [%8s] - ",
3947b37b9149SZdenek Styblik 					feature,
3948c18ec02fSPetter Reinholdtsen 					(feature & 0x1) == 1 ? "Source" : "Receiver");
3949c18ec02fSPetter Reinholdtsen 			printf(" Dep. CLK-ID: 0x%02x\n", dep_chn_id);
3950c18ec02fSPetter Reinholdtsen 		}
3951c18ec02fSPetter Reinholdtsen 		/* direct desc */
3952c18ec02fSPetter Reinholdtsen 		for (j = 0; j < direct_cnt; j++) {
3953b37b9149SZdenek Styblik 			unsigned char feature;
3954b37b9149SZdenek Styblik 			unsigned char family;
3955b37b9149SZdenek Styblik 			unsigned char accuracy;
3956b37b9149SZdenek Styblik 			unsigned long freq;
3957b37b9149SZdenek Styblik 			unsigned long min_freq;
3958b37b9149SZdenek Styblik 			unsigned long max_freq;
3959c18ec02fSPetter Reinholdtsen 
3960c18ec02fSPetter Reinholdtsen 			feature = record->data[offset++];
3961c18ec02fSPetter Reinholdtsen 			family = record->data[offset++];
3962c18ec02fSPetter Reinholdtsen 			accuracy = record->data[offset++];
3963c18ec02fSPetter Reinholdtsen 			freq = (record->data[offset+0] << 0)
3964c18ec02fSPetter Reinholdtsen 				| (record->data[offset+1] << 8)
3965c18ec02fSPetter Reinholdtsen 				| (record->data[offset+2] << 16)
3966c18ec02fSPetter Reinholdtsen 				| (record->data[offset+3] << 24);
3967c18ec02fSPetter Reinholdtsen 			offset += 4;
3968c18ec02fSPetter Reinholdtsen 			min_freq = (record->data[offset+0] << 0)
3969c18ec02fSPetter Reinholdtsen 				| (record->data[offset+1] << 8)
3970c18ec02fSPetter Reinholdtsen 				| (record->data[offset+2] << 16)
3971c18ec02fSPetter Reinholdtsen 				| (record->data[offset+3] << 24);
3972c18ec02fSPetter Reinholdtsen 			offset += 4;
3973c18ec02fSPetter Reinholdtsen 			max_freq = (record->data[offset+0] << 0)
3974c18ec02fSPetter Reinholdtsen 				| (record->data[offset+1] << 8)
3975c18ec02fSPetter Reinholdtsen 				| (record->data[offset+2] << 16)
3976c18ec02fSPetter Reinholdtsen 				| (record->data[offset+3] << 24);
3977c18ec02fSPetter Reinholdtsen 			offset += 4;
3978c18ec02fSPetter Reinholdtsen 
3979c18ec02fSPetter Reinholdtsen 			printf("\t- Feature: 0x%02x    - PLL: %x / Asym: %s\n",
3980c18ec02fSPetter Reinholdtsen 					feature,
3981c18ec02fSPetter Reinholdtsen 					(feature > 1) & 1,
3982c18ec02fSPetter Reinholdtsen 					(feature & 1) ? "Source" : "Receiver");
3983b37b9149SZdenek Styblik 			printf("\tFamily:  0x%02x    - AccLVL: 0x%02x\n",
3984b37b9149SZdenek Styblik 					family, accuracy);
3985c18ec02fSPetter Reinholdtsen 			printf("\tFRQ: %-9ld - min: %-9ld - max: %-9ld\n",
3986c18ec02fSPetter Reinholdtsen 					freq, min_freq, max_freq);
3987c18ec02fSPetter Reinholdtsen 		}
3988c18ec02fSPetter Reinholdtsen 		printf("\n");
3989c18ec02fSPetter Reinholdtsen 	}
3990c18ec02fSPetter Reinholdtsen }
3991c18ec02fSPetter Reinholdtsen 
3992c18ec02fSPetter Reinholdtsen /**************************************************************************
3993c18ec02fSPetter Reinholdtsen *
3994c18ec02fSPetter Reinholdtsen * Function name: ipmi_ekanalyzer_fru_file2structure
3995c18ec02fSPetter Reinholdtsen *
3996c18ec02fSPetter Reinholdtsen * Description: this function convert a FRU binary file into a linked list of
3997c18ec02fSPetter Reinholdtsen *              FRU multi record
3998c18ec02fSPetter Reinholdtsen *
3999c18ec02fSPetter Reinholdtsen * Restriction: None
4000c18ec02fSPetter Reinholdtsen *
4001c18ec02fSPetter Reinholdtsen * Input/Ouput: filename1: name of the file that contain FRU binary data
4002c18ec02fSPetter Reinholdtsen *        record: a pointer to current record
4003c18ec02fSPetter Reinholdtsen *        list_head: a pointer to header of the list
4004c18ec02fSPetter Reinholdtsen *        list_last: a pointer to tale of the list
4005c18ec02fSPetter Reinholdtsen *
4006c18ec02fSPetter Reinholdtsen * Global: None
4007c18ec02fSPetter Reinholdtsen *
4008c18ec02fSPetter Reinholdtsen * Return: return -1 as Error status, and 0 as Ok status
4009c18ec02fSPetter Reinholdtsen *
4010c18ec02fSPetter Reinholdtsen ***************************************************************************/
4011c18ec02fSPetter Reinholdtsen static int
ipmi_ekanalyzer_fru_file2structure(char * filename,struct ipmi_ek_multi_header ** list_head,struct ipmi_ek_multi_header ** list_record,struct ipmi_ek_multi_header ** list_last)4012c18ec02fSPetter Reinholdtsen ipmi_ekanalyzer_fru_file2structure(char *filename,
4013c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header **list_head,
4014c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header **list_record,
4015c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header **list_last)
4016c18ec02fSPetter Reinholdtsen {
4017c18ec02fSPetter Reinholdtsen 	FILE *input_file;
4018c18ec02fSPetter Reinholdtsen 	unsigned char data;
4019c18ec02fSPetter Reinholdtsen 	unsigned char last_record = 0;
4020c18ec02fSPetter Reinholdtsen 	unsigned int multi_offset = 0;
4021c18ec02fSPetter Reinholdtsen 	int record_count = 0;
4022c18ec02fSPetter Reinholdtsen 	int ret = 0;
4023c18ec02fSPetter Reinholdtsen 
4024c18ec02fSPetter Reinholdtsen 	input_file = fopen(filename, "r");
4025c18ec02fSPetter Reinholdtsen 	if (input_file == NULL) {
4026c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "File: '%s' is not found", filename);
4027c18ec02fSPetter Reinholdtsen 		return ERROR_STATUS;
4028c18ec02fSPetter Reinholdtsen 	}
4029c18ec02fSPetter Reinholdtsen 
4030c18ec02fSPetter Reinholdtsen 	fseek(input_file, START_DATA_OFFSET, SEEK_SET);
4031c18ec02fSPetter Reinholdtsen 	data = 0;
4032c18ec02fSPetter Reinholdtsen 	ret = fread(&data, 1, 1, input_file);
4033c18ec02fSPetter Reinholdtsen 	if ((ret != 1) || ferror(input_file)) {
4034c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid Offset!");
4035c18ec02fSPetter Reinholdtsen 		fclose(input_file);
4036c18ec02fSPetter Reinholdtsen 		return ERROR_STATUS;
4037c18ec02fSPetter Reinholdtsen 	}
4038c18ec02fSPetter Reinholdtsen 	if (data == 0) {
4039c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "There is no multi record in the file '%s'",
4040c18ec02fSPetter Reinholdtsen 				filename);
4041c18ec02fSPetter Reinholdtsen 		fclose(input_file);
4042c18ec02fSPetter Reinholdtsen 		return ERROR_STATUS;
4043c18ec02fSPetter Reinholdtsen 	}
4044c18ec02fSPetter Reinholdtsen 	/* the offset value is in multiple of 8 bytes. */
4045c18ec02fSPetter Reinholdtsen 	multi_offset = data * 8;
4046c18ec02fSPetter Reinholdtsen 	lprintf(LOG_DEBUG, "start multi offset = 0x%02x",
4047c18ec02fSPetter Reinholdtsen 			multi_offset);
4048c18ec02fSPetter Reinholdtsen 
4049c18ec02fSPetter Reinholdtsen 	fseek(input_file, multi_offset, SEEK_SET);
4050c18ec02fSPetter Reinholdtsen 	while (!feof(input_file)) {
4051b37b9149SZdenek Styblik 		/* TODO - check malloc() */
4052c18ec02fSPetter Reinholdtsen 		*list_record = malloc(sizeof(struct ipmi_ek_multi_header));
4053c18ec02fSPetter Reinholdtsen 		ret = fread(&(*list_record)->header, START_DATA_OFFSET, 1,
4054c18ec02fSPetter Reinholdtsen 				input_file);
4055c18ec02fSPetter Reinholdtsen 		if ((ret != 1) || ferror(input_file)) {
4056b37b9149SZdenek Styblik 			/* TODO - no free?! */
4057c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid Header!");
4058c18ec02fSPetter Reinholdtsen 			fclose(input_file);
4059c18ec02fSPetter Reinholdtsen 			return ERROR_STATUS;
4060c18ec02fSPetter Reinholdtsen 		}
4061c18ec02fSPetter Reinholdtsen 		if ((*list_record)->header.len == 0) {
4062c18ec02fSPetter Reinholdtsen 			record_count++;
4063c18ec02fSPetter Reinholdtsen 			continue;
4064c18ec02fSPetter Reinholdtsen 		}
4065c18ec02fSPetter Reinholdtsen 		(*list_record)->data = malloc((*list_record)->header.len);
4066c18ec02fSPetter Reinholdtsen 		if ((*list_record)->data == NULL) {
4067c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Failed to allocation memory size %d\n",
4068c18ec02fSPetter Reinholdtsen 					(*list_record)->header.len);
4069c18ec02fSPetter Reinholdtsen 			record_count++;
4070c18ec02fSPetter Reinholdtsen 			continue;
4071c18ec02fSPetter Reinholdtsen 		}
4072c18ec02fSPetter Reinholdtsen 
4073c18ec02fSPetter Reinholdtsen 		ret = fread((*list_record)->data, ((*list_record)->header.len),
4074c18ec02fSPetter Reinholdtsen 				1, input_file);
4075c18ec02fSPetter Reinholdtsen 		if ((ret != 1) || ferror(input_file)) {
4076c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid Record Data!");
4077c18ec02fSPetter Reinholdtsen 			fclose(input_file);
4078c18ec02fSPetter Reinholdtsen 			return ERROR_STATUS;
4079c18ec02fSPetter Reinholdtsen 		}
4080c18ec02fSPetter Reinholdtsen 		if (verbose > 0)
4081c18ec02fSPetter Reinholdtsen 			printf("Record %d has length = %02x\n", record_count,
4082c18ec02fSPetter Reinholdtsen 					(*list_record)->header.len);
4083c18ec02fSPetter Reinholdtsen 		if (verbose > 1) {
4084c18ec02fSPetter Reinholdtsen 			int i;
4085c18ec02fSPetter Reinholdtsen 			printf("Type: %02x", (*list_record)->header.type);
4086c18ec02fSPetter Reinholdtsen 			for (i = 0; i < ((*list_record)->header.len); i++) {
4087c18ec02fSPetter Reinholdtsen 				if (!(i % 8)) {
4088c18ec02fSPetter Reinholdtsen 					printf("\n0x%02x: ", i);
4089c18ec02fSPetter Reinholdtsen 				}
4090c18ec02fSPetter Reinholdtsen 				printf("%02x ",
4091c18ec02fSPetter Reinholdtsen 					(*list_record)->data[i]);
4092c18ec02fSPetter Reinholdtsen 			}
4093c18ec02fSPetter Reinholdtsen 			printf("\n\n");
4094c18ec02fSPetter Reinholdtsen 		}
4095c18ec02fSPetter Reinholdtsen 		ipmi_ek_add_record2list(list_record, list_head, list_last);
4096c18ec02fSPetter Reinholdtsen 		/* mask the 8th bits to see if it is the last record */
4097c18ec02fSPetter Reinholdtsen 		last_record = ((*list_record)->header.format) & 0x80;
4098c18ec02fSPetter Reinholdtsen 		if (last_record) {
4099c18ec02fSPetter Reinholdtsen 			break;
4100c18ec02fSPetter Reinholdtsen 		}
4101c18ec02fSPetter Reinholdtsen 		record_count++;
4102c18ec02fSPetter Reinholdtsen 	}
4103c18ec02fSPetter Reinholdtsen 	fclose(input_file);
4104c18ec02fSPetter Reinholdtsen 	return OK_STATUS;
4105c18ec02fSPetter Reinholdtsen }
4106c18ec02fSPetter Reinholdtsen 
4107c18ec02fSPetter Reinholdtsen /**************************************************************************
4108c18ec02fSPetter Reinholdtsen *
4109c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_add_record2list
4110c18ec02fSPetter Reinholdtsen *
4111c18ec02fSPetter Reinholdtsen * Description: this function adds a sigle FRU multi record to a linked list of
4112c18ec02fSPetter Reinholdtsen *              FRU multi record.
4113c18ec02fSPetter Reinholdtsen *
4114c18ec02fSPetter Reinholdtsen * Restriction: None
4115c18ec02fSPetter Reinholdtsen *
4116c18ec02fSPetter Reinholdtsen * Input/Output: record: a pointer to current record
4117c18ec02fSPetter Reinholdtsen *        list_head: a pointer to header of the list
4118c18ec02fSPetter Reinholdtsen *        list_last: a pointer to tale of the list
4119c18ec02fSPetter Reinholdtsen *
4120c18ec02fSPetter Reinholdtsen * Global: None
4121c18ec02fSPetter Reinholdtsen *
4122c18ec02fSPetter Reinholdtsen * Return: None
4123c18ec02fSPetter Reinholdtsen *
4124c18ec02fSPetter Reinholdtsen ***************************************************************************/
4125c18ec02fSPetter Reinholdtsen static void
ipmi_ek_add_record2list(struct ipmi_ek_multi_header ** record,struct ipmi_ek_multi_header ** list_head,struct ipmi_ek_multi_header ** list_last)4126c18ec02fSPetter Reinholdtsen ipmi_ek_add_record2list(struct ipmi_ek_multi_header **record,
4127c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header **list_head,
4128c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header **list_last)
4129c18ec02fSPetter Reinholdtsen {
4130c18ec02fSPetter Reinholdtsen 	if (*list_head == NULL) {
4131c18ec02fSPetter Reinholdtsen 		*list_head = *record;
4132c18ec02fSPetter Reinholdtsen 		(*record)->prev = NULL;
4133b37b9149SZdenek Styblik 		if (verbose > 2) {
4134c18ec02fSPetter Reinholdtsen 			printf("Adding first record to list\n");
4135c18ec02fSPetter Reinholdtsen 		}
4136b37b9149SZdenek Styblik 	} else {
4137c18ec02fSPetter Reinholdtsen 		(*list_last)->next = *record;
4138c18ec02fSPetter Reinholdtsen 		(*record)->prev = *list_last;
4139b37b9149SZdenek Styblik 		if (verbose > 2) {
4140c18ec02fSPetter Reinholdtsen 			printf("Add 1 record to list\n");
4141c18ec02fSPetter Reinholdtsen 		}
4142b37b9149SZdenek Styblik 	}
4143c18ec02fSPetter Reinholdtsen 	*list_last = *record;
4144c18ec02fSPetter Reinholdtsen 	(*record)->next = NULL;
4145c18ec02fSPetter Reinholdtsen }
4146c18ec02fSPetter Reinholdtsen 
4147c18ec02fSPetter Reinholdtsen /**************************************************************************
4148c18ec02fSPetter Reinholdtsen *
4149c18ec02fSPetter Reinholdtsen * Function name: ipmi_ek_remove_record_from_list
4150c18ec02fSPetter Reinholdtsen *
4151c18ec02fSPetter Reinholdtsen * Description: this function removes a sigle FRU multi record from a linked
4152c18ec02fSPetter Reinholdtsen *              list of FRU multi record.
4153c18ec02fSPetter Reinholdtsen *
4154c18ec02fSPetter Reinholdtsen * Restriction: None
4155c18ec02fSPetter Reinholdtsen *
4156c18ec02fSPetter Reinholdtsen * Input/Output: record: a pointer to record to be deleted
4157c18ec02fSPetter Reinholdtsen *        list_head: a pointer to header of the list
4158c18ec02fSPetter Reinholdtsen *        list_last: a pointer to tale of the list
4159c18ec02fSPetter Reinholdtsen *
4160c18ec02fSPetter Reinholdtsen * Global: None
4161c18ec02fSPetter Reinholdtsen *
4162c18ec02fSPetter Reinholdtsen * Return: None
4163c18ec02fSPetter Reinholdtsen *
4164c18ec02fSPetter Reinholdtsen ***************************************************************************/
4165c18ec02fSPetter Reinholdtsen static void
ipmi_ek_remove_record_from_list(struct ipmi_ek_multi_header * record,struct ipmi_ek_multi_header ** list_head,struct ipmi_ek_multi_header ** list_last)4166c18ec02fSPetter Reinholdtsen ipmi_ek_remove_record_from_list(struct ipmi_ek_multi_header *record,
4167c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header **list_head,
4168c18ec02fSPetter Reinholdtsen 		struct ipmi_ek_multi_header **list_last)
4169c18ec02fSPetter Reinholdtsen {
4170b37b9149SZdenek Styblik 	if (record->prev == NULL) {
4171c18ec02fSPetter Reinholdtsen 		*list_head = record->next;
4172b37b9149SZdenek Styblik 	} else {
4173c18ec02fSPetter Reinholdtsen 		record->prev->next = record->next;
4174b37b9149SZdenek Styblik 	}
4175b37b9149SZdenek Styblik 	if (record->next == NULL) {
4176c18ec02fSPetter Reinholdtsen 		(*list_last) = record->prev;
4177b37b9149SZdenek Styblik 	} else {
4178c18ec02fSPetter Reinholdtsen 		record->next->prev = record->prev;
4179b37b9149SZdenek Styblik 	}
4180c18ec02fSPetter Reinholdtsen 	free(record);
4181c18ec02fSPetter Reinholdtsen 	record = NULL;
4182c18ec02fSPetter Reinholdtsen }
4183