Преглед изворни кода

[bofm] Add core BOFM library

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown пре 13 година
родитељ
комит
5597d52c21
4 измењених фајлова са 678 додато и 0 уклоњено
  1. 1
    0
      src/Makefile
  2. 341
    0
      src/include/ipxe/bofm.h
  3. 1
    0
      src/include/ipxe/errfile.h
  4. 335
    0
      src/interface/bofm/bofm.c

+ 1
- 0
src/Makefile Прегледај датотеку

@@ -75,6 +75,7 @@ SRCDIRS		+= drivers/nvs
75 75
 SRCDIRS		+= drivers/bitbash
76 76
 SRCDIRS		+= drivers/infiniband
77 77
 SRCDIRS		+= interface/pxe interface/efi interface/smbios
78
+SRCDIRS		+= interface/bofm
78 79
 SRCDIRS		+= tests
79 80
 SRCDIRS		+= crypto crypto/axtls crypto/matrixssl
80 81
 SRCDIRS		+= hci hci/commands hci/tui

+ 341
- 0
src/include/ipxe/bofm.h Прегледај датотеку

@@ -0,0 +1,341 @@
1
+#ifndef _IPXE_BOFM_H
2
+#define _IPXE_BOFM_H
3
+
4
+/**
5
+ * @file
6
+ *
7
+ * IBM BladeCenter Open Fabric Manager (BOFM)
8
+ *
9
+ */
10
+
11
+FILE_LICENCE ( GPL2_OR_LATER );
12
+
13
+#include <stdint.h>
14
+#include <ipxe/list.h>
15
+#include <ipxe/pci.h>
16
+
17
+/** 'IBM ' signature
18
+ *
19
+ * Present in %edi when the BIOS initialisation entry point is called,
20
+ * with the BOFM table pointer in %esi.
21
+ *
22
+ * Defined in section 4.1.2 of the POST/BIOS BOFM I/O Address
23
+ * Re-Assignment Architecture document.
24
+ */
25
+#define IBMs_SIGNATURE ( ( 'I' << 24 ) + ( 'B' << 16 ) + ( 'M' << 8 ) + ' ' )
26
+
27
+/** ' IBM' signature
28
+ *
29
+ * Returned in %edi from the BIOS initialisation entry point, with the
30
+ * return code in %dl.
31
+ *
32
+ * Defined in section 4.1.2 of the POST/BIOS BOFM I/O Address
33
+ * Re-Assignment Architecture document.
34
+ */
35
+#define sIBM_SIGNATURE ( ( ' ' << 24 ) + ( 'I' << 16 ) + ( 'B' << 8 ) + 'M' )
36
+
37
+/** @defgroup bofmrc BOFM return codes
38
+ *
39
+ * Defined in section 4.1.3 of the POST/BIOS BOFM I/O Address
40
+ * Re-Assignment Architecture document.
41
+ *
42
+ * @{
43
+ */
44
+
45
+/** Successful */
46
+#define BOFM_SUCCESS 0x00
47
+
48
+/** Invalid action string */
49
+#define BOFM_ERR_INVALID_ACTION 0x01
50
+
51
+/** Unsupported parameter structure version */
52
+#define BOFM_ERR_UNSUPPORTED 0x02
53
+
54
+/** Device error prohibited MAC/WWN update */
55
+#define BOFM_ERR_DEVICE_ERROR 0x03
56
+
57
+/** PCI reset required (may be combined with another return code) */
58
+#define BOFM_PCI_RESET 0x80
59
+
60
+/** @} */
61
+
62
+/** Skip option ROM initialisation
63
+ *
64
+ * A BOFM BIOS may call the initialisation entry point multiple times;
65
+ * only the last call should result in actual initialisation.
66
+ *
67
+ * This flag is internal to iPXE.
68
+ */
69
+#define BOFM_SKIP_INIT 0x80000000UL
70
+
71
+/** BOFM table header
72
+ *
73
+ * Defined in section 4.1 of the Open Fabric Manager Parameter
74
+ * Specification document.
75
+ */
76
+struct bofm_global_header {
77
+	/** Signature */
78
+	uint32_t magic;
79
+	/** Subsignature (action string) */
80
+	uint32_t action;
81
+	/** Data structure version */
82
+	uint8_t version;
83
+	/** Data structure level */
84
+	uint8_t level;
85
+	/** Data structure length */
86
+	uint16_t length;
87
+	/** Data structure checksum */
88
+	uint8_t checksum;
89
+	/** Data structure profile */
90
+	char profile[32];
91
+	/** Data structure global options */
92
+	uint32_t options;
93
+	/** Data structure sequence stamp */
94
+	uint32_t sequence;
95
+} __attribute__ (( packed ));
96
+
97
+/** BOFM table header signature
98
+ *
99
+ * Defined in section 4.1.2 of the POST/BIOS BOFM I/O Address
100
+ * Re-Assignment Architecture document.
101
+ */
102
+#define BOFM_IOAA_MAGIC	 ( 'I' + ( 'O' << 8 ) + ( 'A' << 16 ) + ( 'A' << 24 ) )
103
+
104
+/** @defgroup bofmaction BOFM header subsignatures (action strings)
105
+ *
106
+ * Defined in section 4.1.2 of the POST/BIOS BOFM I/O Address
107
+ * Re-Assignment Architecture document.
108
+ *
109
+ * @{
110
+ */
111
+
112
+/** Update MAC/WWN */
113
+#define BOFM_ACTION_UPDT ( 'U' + ( 'P' << 8 ) + ( 'D' << 16 ) + ( 'T' << 24 ) )
114
+
115
+/** Restore MAC/WWN to factory default */
116
+#define BOFM_ACTION_DFLT ( 'D' + ( 'F' << 8 ) + ( 'L' << 16 ) + ( 'T' << 24 ) )
117
+
118
+/** Harvest MAC/WWN */
119
+#define BOFM_ACTION_HVST ( 'H' + ( 'V' << 8 ) + ( 'S' << 16 ) + ( 'T' << 24 ) )
120
+
121
+/** Update MAC/WWN and initialise device */
122
+#define BOFM_ACTION_PARM ( 'P' + ( 'A' << 8 ) + ( 'R' << 16 ) + ( 'M' << 24 ) )
123
+
124
+/** Just initialise the device */
125
+#define BOFM_ACTION_NONE ( 'N' + ( 'O' << 8 ) + ( 'N' << 16 ) + ( 'E' << 24 ) )
126
+
127
+/** @} */
128
+
129
+/** BOFM section header
130
+ *
131
+ * Defined in section 4.2 of the Open Fabric Manager Parameter
132
+ * Specification document.
133
+ */
134
+struct bofm_section_header {
135
+	/** Signature */
136
+	uint32_t magic;
137
+	/** Length */
138
+	uint16_t length;
139
+} __attribute__ (( packed ));
140
+
141
+/** @defgroup bofmsections BOFM section header signatures
142
+ *
143
+ * Defined in section 4.2 of the Open Fabric Manager Parameter
144
+ * Specification document.
145
+ *
146
+ * @{
147
+ */
148
+
149
+/** EN start marker */
150
+#define BOFM_EN_MAGIC    ( ' ' + ( ' ' << 8 ) + ( 'E' << 16 ) + ( 'N' << 24 ) )
151
+
152
+/** End marker */
153
+#define BOFM_DONE_MAGIC	 ( 'D' + ( 'O' << 8 ) + ( 'N' << 16 ) + ( 'E' << 24 ) )
154
+
155
+/** @} */
156
+
157
+/** BOFM Ethernet parameter entry
158
+ *
159
+ * Defined in section 5.1 of the Open Fabric Manager Parameter
160
+ * Specification document.
161
+ */
162
+struct bofm_en {
163
+	/** Options */
164
+	uint16_t options;
165
+	/** PCI bus:dev.fn
166
+	 *
167
+	 * Valid only if @c options indicates @c BOFM_EN_MAP_PFA
168
+	 */
169
+	uint16_t busdevfn;
170
+	/** Slot or mezzanine number
171
+	 *
172
+	 * Valid only if @c options indicates @c BOFM_EN_MAP_SLOT_PORT
173
+	 */
174
+	uint8_t slot;
175
+	/** Port number
176
+	 *
177
+	 * Valid only if @c options indicates @c BOFM_EN_MAP_SLOT_PORT
178
+	 */
179
+	uint8_t port;
180
+	/** Multi-port index */
181
+	uint8_t mport;
182
+	/** VLAN tag for MAC address A */
183
+	uint16_t vlan_a;
184
+	/** MAC address A
185
+	 *
186
+	 * MAC address A is the sole MAC address, or the lower
187
+	 * (inclusive) bound of a range of MAC addresses.
188
+	 */
189
+	uint8_t mac_a[6];
190
+	/** VLAN tag for MAC address B */
191
+	uint16_t vlan_b;
192
+	/** MAC address B
193
+	 *
194
+	 * MAC address B is unset, or the upper (inclusive) bound of a
195
+	 * range of MAC addresses
196
+	 */
197
+	uint8_t mac_b[6];
198
+} __attribute__ (( packed ));
199
+
200
+/** @defgroup bofmenopts BOFM Ethernet parameter entry options
201
+ *
202
+ * Defined in section 5.1 of the Open Fabric Manager Parameter
203
+ * Specification document.
204
+ *
205
+ * @{
206
+ */
207
+
208
+/** Port mapping mask */
209
+#define BOFM_EN_MAP_MASK	0x0001
210
+
211
+/** Port mapping is by PCI bus:dev.fn */
212
+#define BOFM_EN_MAP_PFA			0x0000
213
+
214
+/** Port mapping is by slot/port */
215
+#define BOFM_EN_MAP_SLOT_PORT		0x0001
216
+
217
+/** MAC address B is present */
218
+#define BOFM_EN_EN_B		0x0002
219
+
220
+/** VLAN tag for MAC address B is present */
221
+#define BOFM_EN_VLAN_B		0x0004
222
+
223
+/** MAC address A is present */
224
+#define BOFM_EN_EN_A		0x0008
225
+
226
+/** VLAN tag for MAC address A is present */
227
+#define BOFM_EN_VLAN_A		0x0010
228
+
229
+/** Entry consumption indicator mask */
230
+#define BOFM_EN_CSM_MASK	0x00c0
231
+
232
+/** Entry has not been used */
233
+#define BOFM_EN_CSM_UNUSED		0x0000
234
+
235
+/** Entry has been used successfully */
236
+#define BOFM_EN_CSM_SUCCESS		0x0040
237
+
238
+/** Entry has been used but failed */
239
+#define BOFM_EN_CSM_FAILED		0x0080
240
+
241
+/** Consumed entry change mask */
242
+#define BOFM_EN_CHG_MASK	0x0100
243
+
244
+/** Consumed entry is same as previous active entry */
245
+#define BOFM_EN_CHG_UNCHANGED		0x0000
246
+
247
+/** Consumed entry is different than previous active entry */
248
+#define BOFM_EN_CHG_CHANGED		0x0100
249
+
250
+/** Ignore values - it's harvest time */
251
+#define BOFM_EN_USAGE_HARVEST	0x1000
252
+
253
+/** Use entry values for assignment */
254
+#define BOFM_EN_USAGE_ENTRY	0x0800
255
+
256
+/** Use factory default values */
257
+#define BOFM_EN_USAGE_DEFAULT	0x0400
258
+
259
+/** Harvest complete */
260
+#define BOFM_EN_HVST		0x2000
261
+
262
+/** Harvest request mask */
263
+#define BOFM_EN_RQ_HVST_MASK	0xc000
264
+
265
+/** Do not harvest */
266
+#define BOFM_EN_RQ_HVST_NONE		0x0000
267
+
268
+/** Harvest factory default values */
269
+#define BOFM_EN_RQ_HVST_DEFAULT		0x4000
270
+
271
+/** Harvest active values */
272
+#define BOFM_EN_RQ_HVST_ACTIVE		0xc000
273
+
274
+/** @} */
275
+
276
+/** BOFM magic value debug message format */
277
+#define BOFM_MAGIC_FMT "'%c%c%c%c'"
278
+
279
+/** BOFM magic value debug message arguments */
280
+#define BOFM_MAGIC_ARGS( magic )					\
281
+	( ( (magic) >> 0 ) & 0xff ), ( ( (magic) >> 8 ) & 0xff ),	\
282
+	( ( (magic) >> 16 ) & 0xff ), ( ( (magic) >> 24 ) & 0xff )
283
+
284
+/** A BOFM device */
285
+struct bofm_device {
286
+	/** Underlying PCI device */
287
+	struct pci_device *pci;
288
+	/** BOFM device operations */
289
+	struct bofm_operations *op;
290
+	/** List of BOFM devices */
291
+	struct list_head list;
292
+};
293
+
294
+/** BOFM device operations */
295
+struct bofm_operations {
296
+	/** Harvest Ethernet MAC
297
+	 *
298
+	 * @v bofm		BOFM device
299
+	 * @v mport		Multi-port index
300
+	 * @v mac		MAC to fill in
301
+	 * @ret rc		Return status code
302
+	 */
303
+	int ( * harvest ) ( struct bofm_device *bofm, unsigned int mport,
304
+			    uint8_t *mac );
305
+	/** Update Ethernet MAC
306
+	 *
307
+	 * @v bofm		BOFM device
308
+	 * @v mport		Multi-port index
309
+	 * @v mac		New MAC
310
+	 * @ret rc		Return status code
311
+	 */
312
+	int ( * update ) ( struct bofm_device *bofm, unsigned int mport,
313
+			   const uint8_t *mac );
314
+};
315
+
316
+/** BOFM driver table */
317
+#define BOFM_DRIVERS __table ( struct pci_driver, "bofm_drivers" )
318
+
319
+/** Declare a BOFM driver */
320
+#define __bofm_driver __table_entry ( BOFM_DRIVERS, 01 )
321
+
322
+/**
323
+ * Initialise BOFM device
324
+ *
325
+ * @v bofm		BOFM device
326
+ * @v pci		PCI device
327
+ * @v op		BOFM device operations
328
+ */
329
+static inline __attribute__ (( always_inline )) void
330
+bofm_init ( struct bofm_device *bofm, struct pci_device *pci,
331
+	    struct bofm_operations *op ) {
332
+	bofm->pci = pci;
333
+	bofm->op = op;
334
+}
335
+
336
+extern int bofm_register ( struct bofm_device *bofm );
337
+extern void bofm_unregister ( struct bofm_device *bofm );
338
+extern int bofm_find_driver ( struct pci_device *pci );
339
+extern int bofm ( userptr_t bofmtab, struct pci_device *pci );
340
+
341
+#endif /* _IPXE_BOFM_H */

+ 1
- 0
src/include/ipxe/errfile.h Прегледај датотеку

@@ -236,6 +236,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
236 236
 #define ERRFILE_fcmgmt_cmd	      ( ERRFILE_OTHER | 0x001e0000 )
237 237
 #define ERRFILE_gdbstub_cmd	      ( ERRFILE_OTHER | 0x001f0000 )
238 238
 #define ERRFILE_sanboot_cmd	      ( ERRFILE_OTHER | 0x00200000 )
239
+#define ERRFILE_bofm		      ( ERRFILE_OTHER | 0x00210000 )
239 240
 
240 241
 /** @} */
241 242
 

+ 335
- 0
src/interface/bofm/bofm.c Прегледај датотеку

@@ -0,0 +1,335 @@
1
+/*
2
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <stdint.h>
22
+#include <string.h>
23
+#include <errno.h>
24
+#include <ipxe/uaccess.h>
25
+#include <ipxe/list.h>
26
+#include <ipxe/ethernet.h>
27
+#include <ipxe/bofm.h>
28
+
29
+/** @file
30
+ *
31
+ * IBM BladeCenter Open Fabric Manager (BOFM)
32
+ *
33
+ */
34
+
35
+/** List of BOFM devices */
36
+static LIST_HEAD ( bofmdevs );
37
+
38
+/**
39
+ * Register BOFM device
40
+ *
41
+ * @v bofm		BOFM device
42
+ * @ret rc		Return status code
43
+ */
44
+int bofm_register ( struct bofm_device *bofm ) {
45
+
46
+	list_add ( &bofm->list, &bofmdevs );
47
+	DBG ( "BOFM: " PCI_FMT " registered using driver \"%s\"\n",
48
+	      PCI_ARGS ( bofm->pci ), bofm->pci->id->name );
49
+	return 0;
50
+}
51
+
52
+/**
53
+ * Unregister BOFM device
54
+ *
55
+ * @v bofm		BOFM device
56
+ */
57
+void bofm_unregister ( struct bofm_device *bofm ) {
58
+
59
+	list_del ( &bofm->list );
60
+	DBG ( "BOFM: " PCI_FMT " unregistered\n", PCI_ARGS ( bofm->pci ) );
61
+}
62
+
63
+/**
64
+ * Find BOFM device matching PCI bus:dev.fn address
65
+ *
66
+ * @v busdevfn		PCI bus:dev.fn address
67
+ * @ret bofm		BOFM device, or NULL
68
+ */
69
+static struct bofm_device * bofm_find_busdevfn ( unsigned int busdevfn ) {
70
+	struct bofm_device *bofm;
71
+
72
+	list_for_each_entry ( bofm, &bofmdevs, list ) {
73
+		if ( bofm->pci->busdevfn == busdevfn )
74
+			return bofm;
75
+	}
76
+	return NULL;
77
+}
78
+
79
+/**
80
+ * Find BOFM driver for PCI device
81
+ *
82
+ * @v pci		PCI device
83
+ * @ret rc		Return status code
84
+ */
85
+int bofm_find_driver ( struct pci_device *pci ) {
86
+	struct pci_driver *driver;
87
+	struct pci_device_id *id;
88
+	unsigned int i;
89
+
90
+	for_each_table_entry ( driver, BOFM_DRIVERS ) {
91
+		for ( i = 0 ; i < driver->id_count ; i++ ) {
92
+			id = &driver->ids[i];
93
+			if ( ( id->vendor == pci->vendor ) &&
94
+			     ( id->device == pci->device ) ) {
95
+				pci_set_driver ( pci, driver, id );
96
+				return 0;
97
+			}
98
+		}
99
+	}
100
+	return -ENOENT;
101
+}
102
+
103
+/**
104
+ * Probe PCI device for BOFM driver
105
+ *
106
+ * @v pci		PCI device
107
+ * @ret rc		Return status code
108
+ */
109
+static int bofm_probe ( struct pci_device *pci ) {
110
+	int rc;
111
+
112
+	/* Probe device */
113
+	if ( ( rc = pci_probe ( pci ) ) != 0 ) {
114
+		DBG ( "BOFM: " PCI_FMT " could not load driver: %s\n",
115
+		      PCI_ARGS ( pci ), strerror ( rc ) );
116
+		return rc;
117
+	}
118
+
119
+	return 0;
120
+}
121
+
122
+/**
123
+ * Remove PCI device
124
+ *
125
+ * @v pci		PCI device
126
+ */
127
+static void bofm_remove ( struct pci_device *pci ) {
128
+
129
+	/* Note that the IBM BIOS may re-read the expansion ROM after
130
+	 * the BOFM initialisation call.  The BOFM driver must ensure
131
+	 * that the card is left in a state in which expansion ROM
132
+	 * reads will succeed.  (For example, if a card contains an
133
+	 * embedded CPU that may issue reads to the same underlying
134
+	 * flash device, and these reads are not locked against reads
135
+	 * via the expansion ROM BAR, then the CPU must be stopped.)
136
+	 *
137
+	 * If this is not done, then occasional corrupted reads from
138
+	 * the expansion ROM will be seen, and the BIOS may complain
139
+	 * about a ROM checksum error.
140
+	 */
141
+	pci_remove ( pci );
142
+	DBG ( "BOFM: " PCI_FMT " removed\n", PCI_ARGS ( pci ) );
143
+}
144
+
145
+/**
146
+ * Locate BOFM table section
147
+ *
148
+ * @v bofmtab		BOFM table
149
+ * @v len		Length of BOFM table
150
+ * @v magic		Section magic
151
+ * @v bofmsec		BOFM section header to fill in
152
+ * @ret offset		Offset to section, or 0 if not found
153
+ */
154
+static size_t bofm_locate_section ( userptr_t bofmtab, size_t len,
155
+				    uint32_t magic,
156
+				    struct bofm_section_header *bofmsec ) {
157
+	size_t offset = sizeof ( struct bofm_global_header );
158
+
159
+	while ( offset < len ) {
160
+		copy_from_user ( bofmsec, bofmtab, offset,
161
+				 sizeof ( *bofmsec ) );
162
+		if ( bofmsec->magic == magic )
163
+			return offset;
164
+		if ( bofmsec->magic == BOFM_DONE_MAGIC )
165
+			break;
166
+		offset += ( sizeof ( *bofmsec ) + bofmsec->length );
167
+	}
168
+	return 0;
169
+}
170
+
171
+/**
172
+ * Process BOFM Ethernet parameter entry
173
+ *
174
+ * @v bofm		BOFM device
175
+ * @v en		EN parameter entry
176
+ * @ret rc		Return status code
177
+ */
178
+static int bofm_en ( struct bofm_device *bofm, struct bofm_en *en ) {
179
+	uint8_t mac[6];
180
+	int rc;
181
+
182
+	/* Retrieve current MAC address */
183
+	if ( ( rc = bofm->op->harvest ( bofm, en->mport, mac ) ) != 0 ) {
184
+		DBG ( "BOFM: " PCI_FMT " port %d could not harvest: %s\n",
185
+		      PCI_ARGS ( bofm->pci ), en->mport, strerror ( rc ) );
186
+		return rc;
187
+	}
188
+
189
+	/* Harvest MAC address if necessary */
190
+	if ( en->options & BOFM_EN_RQ_HVST_MASK ) {
191
+		DBG ( "BOFM: " PCI_FMT " port %d harvested MAC %s\n",
192
+		      PCI_ARGS ( bofm->pci ), en->mport, eth_ntoa ( mac ) );
193
+		memcpy ( en->mac_a, mac, sizeof ( en->mac_a ) );
194
+		en->options |= ( BOFM_EN_EN_A | BOFM_EN_HVST );
195
+	}
196
+
197
+	/* Mark as changed if necessary */
198
+	if ( ( en->options & BOFM_EN_EN_A ) &&
199
+	     ( memcmp ( en->mac_a, mac, sizeof ( en->mac_a ) ) != 0 ) ) {
200
+		DBG ( "BOFM: " PCI_FMT " port %d MAC %s",
201
+		      PCI_ARGS ( bofm->pci ), en->mport, eth_ntoa ( mac ) );
202
+		DBG ( " changed to %s\n", eth_ntoa ( en->mac_a ) );
203
+		en->options |= BOFM_EN_CHG_CHANGED;
204
+	}
205
+
206
+	/* Apply MAC address if necessary */
207
+	if ( ( en->options & BOFM_EN_EN_A ) &&
208
+	     ( en->options & BOFM_EN_USAGE_ENTRY ) &&
209
+	     ( ! ( en->options & BOFM_EN_USAGE_HARVEST ) ) ) {
210
+		DBG ( "BOFM: " PCI_FMT " port %d applied MAC %s\n",
211
+		      PCI_ARGS ( bofm->pci ), en->mport,
212
+		      eth_ntoa ( en->mac_a ) );
213
+		memcpy ( mac, en->mac_a, sizeof ( mac ) );
214
+	}
215
+
216
+	/* Store MAC address */
217
+	if ( ( rc = bofm->op->update ( bofm, en->mport, mac ) ) != 0 ) {
218
+		DBG ( "BOFM: " PCI_FMT " port %d could not update: %s\n",
219
+		      PCI_ARGS ( bofm->pci ), en->mport, strerror ( rc ) );
220
+		return rc;
221
+	}
222
+
223
+	return 0;
224
+}
225
+
226
+/**
227
+ * Process BOFM table
228
+ *
229
+ * @v bofmtab		BOFM table
230
+ * @v pci		PCI device
231
+ * @ret bofmrc		BOFM return status
232
+ */
233
+int bofm ( userptr_t bofmtab, struct pci_device *pci ) {
234
+	struct bofm_global_header bofmhdr;
235
+	struct bofm_section_header bofmsec;
236
+	struct bofm_en en;
237
+	struct bofm_device *bofm;
238
+	size_t en_region_offset;
239
+	size_t en_offset;
240
+	int skip;
241
+	int rc;
242
+	int bofmrc;
243
+
244
+	/* Read BOFM structure */
245
+	copy_from_user ( &bofmhdr, bofmtab, 0, sizeof ( bofmhdr ) );
246
+	if ( bofmhdr.magic != BOFM_IOAA_MAGIC ) {
247
+		DBG ( "BOFM: invalid table signature " BOFM_MAGIC_FMT "\n",
248
+		      BOFM_MAGIC_ARGS ( bofmhdr.magic ) );
249
+		bofmrc = BOFM_ERR_INVALID_ACTION;
250
+		goto err_bad_signature;
251
+	}
252
+	DBG ( "BOFM: " BOFM_MAGIC_FMT " (profile \"%s\")\n",
253
+	      BOFM_MAGIC_ARGS ( bofmhdr.action ), bofmhdr.profile );
254
+
255
+	/* Determine whether or not we should skip normal POST
256
+	 * initialisation.
257
+	 */
258
+	switch ( bofmhdr.action ) {
259
+	case BOFM_ACTION_UPDT:
260
+	case BOFM_ACTION_DFLT:
261
+	case BOFM_ACTION_HVST:
262
+		skip = BOFM_SKIP_INIT;
263
+		break;
264
+	case BOFM_ACTION_PARM:
265
+	case BOFM_ACTION_NONE:
266
+		skip = 0;
267
+		break;
268
+	default:
269
+		DBG ( "BOFM: invalid action " BOFM_MAGIC_FMT "\n",
270
+		      BOFM_MAGIC_ARGS ( bofmhdr.action ) );
271
+		bofmrc = BOFM_ERR_INVALID_ACTION;
272
+		goto err_bad_action;
273
+	}
274
+
275
+	/* Find BOFM driver */
276
+	if ( ( rc = bofm_find_driver ( pci ) ) != 0 ) {
277
+		DBG ( "BOFM: " PCI_FMT " has no driver\n", PCI_ARGS ( pci ) );
278
+		bofmrc = BOFM_ERR_DEVICE_ERROR;
279
+		goto err_find_driver;
280
+	}
281
+
282
+	/* Probe driver for PCI device */
283
+	if ( ( rc = bofm_probe ( pci ) ) != 0 ) {
284
+		bofmrc = BOFM_ERR_DEVICE_ERROR;
285
+		goto err_probe;
286
+	}
287
+
288
+	/* Locate EN section, if present */
289
+	en_region_offset = bofm_locate_section ( bofmtab, bofmhdr.length,
290
+						 BOFM_EN_MAGIC, &bofmsec );
291
+	if ( ! en_region_offset ) {
292
+		DBG ( "BOFM: No EN section found\n" );
293
+		bofmrc = ( BOFM_SUCCESS | skip );
294
+		goto err_no_en_section;
295
+	}
296
+
297
+	/* Iterate through EN entries */
298
+	for ( en_offset = ( en_region_offset + sizeof ( bofmsec ) ) ;
299
+	      en_offset < ( en_region_offset + sizeof ( bofmsec ) +
300
+			    bofmsec.length ) ; en_offset += sizeof ( en ) ) {
301
+		copy_from_user ( &en, bofmtab, en_offset, sizeof ( en ) );
302
+		DBG2 ( "BOFM: EN entry found:\n" );
303
+		DBG2_HDA ( en_offset, &en, sizeof ( en ) );
304
+		if ( ( en.options & BOFM_EN_MAP_MASK ) != BOFM_EN_MAP_PFA ) {
305
+			DBG ( "BOFM: slot %d port %d has no PCI mapping\n",
306
+			      en.slot, en.port );
307
+			continue;
308
+		}
309
+		bofm = bofm_find_busdevfn ( en.busdevfn );
310
+		if ( ! bofm ) {
311
+			DBG ( "BOFM: " PCI_FMT " ignored\n",
312
+			      PCI_BUS ( en.busdevfn ), PCI_SLOT ( en.busdevfn ),
313
+			      PCI_FUNC ( en.busdevfn ) );
314
+			continue;
315
+		}
316
+		if ( ( rc = bofm_en ( bofm, &en ) ) == 0 ) {
317
+			en.options |= BOFM_EN_CSM_SUCCESS;
318
+		} else {
319
+			en.options |= BOFM_EN_CSM_FAILED;
320
+		}
321
+		DBG2 ( "BOFM: EN entry after processing:\n" );
322
+		DBG2_HDA ( en_offset, &en, sizeof ( en ) );
323
+		copy_to_user ( bofmtab, en_offset, &en, sizeof ( en ) );
324
+	}
325
+
326
+	bofmrc = ( BOFM_SUCCESS | skip );
327
+
328
+ err_no_en_section:
329
+	bofm_remove ( pci );
330
+ err_probe:
331
+ err_find_driver:
332
+ err_bad_action:
333
+ err_bad_signature:
334
+	return bofmrc;
335
+}

Loading…
Откажи
Сачувај