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