|
@@ -21,6 +21,7 @@
|
21
|
21
|
#include <string.h>
|
22
|
22
|
#include <pxe.h>
|
23
|
23
|
#include <realmode.h>
|
|
24
|
+#include <bios.h>
|
24
|
25
|
|
25
|
26
|
/** @file
|
26
|
27
|
*
|
|
@@ -62,14 +63,15 @@ static int pxedrv_parse_pxeromid ( struct pxe_driver *pxedrv,
|
62
|
63
|
}
|
63
|
64
|
|
64
|
65
|
/* Fill in PXE driver loader fields */
|
65
|
|
- pxedrv->loader.segment = pxedrv->rom_segment;
|
66
|
|
- pxedrv->loader.offset = undiloader;
|
|
66
|
+ pxedrv->loader_entry.segment = pxedrv->rom_segment;
|
|
67
|
+ pxedrv->loader_entry.offset = undiloader;
|
67
|
68
|
pxedrv->code_size = undi_rom_id.CodeSize;
|
68
|
69
|
pxedrv->data_size = undi_rom_id.DataSize;
|
69
|
70
|
|
70
|
71
|
DBGC ( pxedrv, "PXEDRV %p has UNDI loader at %04x:%04x "
|
71
|
|
- "(code %04x data %04x)\n", pxedrv, pxedrv->loader.segment,
|
72
|
|
- pxedrv->loader.offset, pxedrv->code_size, pxedrv->data_size );
|
|
72
|
+ "(code %04x data %04x)\n", pxedrv,
|
|
73
|
+ pxedrv->loader_entry.segment, pxedrv->loader_entry.offset,
|
|
74
|
+ pxedrv->code_size, pxedrv->data_size );
|
73
|
75
|
return 0;
|
74
|
76
|
}
|
75
|
77
|
|
|
@@ -221,3 +223,86 @@ struct pxe_driver * pxedrv_find_pci_driver ( unsigned int vendor_id,
|
221
|
223
|
vendor_id, device_id, rombase );
|
222
|
224
|
return NULL;
|
223
|
225
|
}
|
|
226
|
+
|
|
227
|
+/** Parameter block for calling UNDI loader */
|
|
228
|
+static struct s_UNDI_LOADER __data16 ( undi_loader );
|
|
229
|
+#define undi_loader __use_data16 ( undi_loader )
|
|
230
|
+
|
|
231
|
+/** UNDI loader entry point */
|
|
232
|
+static SEGOFF16_t __data16 ( undi_loader_entry );
|
|
233
|
+#define undi_loader_entry __use_data16 ( undi_loader_entry )
|
|
234
|
+
|
|
235
|
+/**
|
|
236
|
+ * Call UNDI loader to create a pixie
|
|
237
|
+ *
|
|
238
|
+ * @v pxedrv PXE driver
|
|
239
|
+ * @v pxe PXE device to be created
|
|
240
|
+ * @v pci_busdevfn PCI bus:dev.fn (PCI devices only), or 0
|
|
241
|
+ * @v isapnp_csn ISAPnP Card Select Number, or -1U
|
|
242
|
+ * @v isapnp_read_port ISAPnP read port, or -1U
|
|
243
|
+ * @ret rc Return status code
|
|
244
|
+ */
|
|
245
|
+static int pxedrv_load ( struct pxe_driver *pxedrv, struct pxe_device *pxe,
|
|
246
|
+ unsigned int pci_busdevfn, unsigned int isapnp_csn,
|
|
247
|
+ unsigned int isapnp_read_port ) {
|
|
248
|
+ int discard;
|
|
249
|
+ uint16_t exit;
|
|
250
|
+ uint16_t fbms;
|
|
251
|
+ unsigned int fbms_seg;
|
|
252
|
+ int rc;
|
|
253
|
+
|
|
254
|
+ memset ( &undi_loader, 0, sizeof ( undi_loader ) );
|
|
255
|
+ undi_loader.AX = pci_busdevfn;
|
|
256
|
+ undi_loader.BX = isapnp_csn;
|
|
257
|
+ undi_loader.DX = isapnp_read_port;
|
|
258
|
+
|
|
259
|
+ /* Allocate base memory for PXE stack */
|
|
260
|
+ get_real ( fbms, BDA_SEG, BDA_FBMS );
|
|
261
|
+ fbms_seg = ( fbms << 6 );
|
|
262
|
+ fbms_seg -= ( ( pxedrv->data_size + 0x0f ) >> 4 );
|
|
263
|
+ undi_loader.UNDI_DS = fbms_seg;
|
|
264
|
+ fbms_seg -= ( ( pxedrv->code_size + 0x0f ) >> 4 );
|
|
265
|
+ undi_loader.UNDI_CS = fbms_seg;
|
|
266
|
+ DBGC ( pxedrv, "PXEDRV %p loading to CS %04x and DS %04x\n", pxedrv,
|
|
267
|
+ undi_loader.UNDI_CS, undi_loader.UNDI_DS );
|
|
268
|
+
|
|
269
|
+ /* Call loader */
|
|
270
|
+ undi_loader_entry = pxedrv->loader_entry;
|
|
271
|
+ __asm__ __volatile__ ( REAL_CODE ( "pushw %%ds\n\t"
|
|
272
|
+ "pushw %w0\n\t"
|
|
273
|
+ "lcall *%c3\n\t"
|
|
274
|
+ "addw $4, %%sp\n\t" )
|
|
275
|
+ : "=a" ( exit ), "=r" ( discard )
|
|
276
|
+ : "0" ( & __from_data16 ( undi_loader ) ),
|
|
277
|
+ "p" ( & __from_data16 ( undi_loader_entry )));
|
|
278
|
+ if ( exit != PXENV_EXIT_SUCCESS ) {
|
|
279
|
+ rc = -undi_loader.Status;
|
|
280
|
+ if ( rc == 0 ) /* Paranoia */
|
|
281
|
+ rc = -EIO;
|
|
282
|
+ DBGC ( pxedrv, "PXEDRV %p loader failed: %s\n",
|
|
283
|
+ strerror ( rc ) );
|
|
284
|
+ return rc;
|
|
285
|
+ }
|
|
286
|
+
|
|
287
|
+ /* Update free base memory counter */
|
|
288
|
+ fbms = ( fbms_seg >> 6 );
|
|
289
|
+ put_real ( fbms, BDA_SEG, BDA_FBMS );
|
|
290
|
+
|
|
291
|
+ /* Record location of pixie in PXE device structure */
|
|
292
|
+ pxe->pxenv = undi_loader.PXENVptr;
|
|
293
|
+ pxe->ppxe = undi_loader.PXEptr;
|
|
294
|
+ return 0;
|
|
295
|
+}
|
|
296
|
+
|
|
297
|
+/**
|
|
298
|
+ * Call UNDI loader to create a pixie
|
|
299
|
+ *
|
|
300
|
+ * @v pxedrv PXE driver
|
|
301
|
+ * @v pxe PXE device to be created
|
|
302
|
+ * @v pci_busdevfn PCI bus:dev.fn
|
|
303
|
+ * @ret rc Return status code
|
|
304
|
+ */
|
|
305
|
+int pxedrv_load_pci ( struct pxe_driver *pxedrv, struct pxe_device *pxe,
|
|
306
|
+ unsigned int bus, unsigned int devfn ) {
|
|
307
|
+ return pxedrv_load ( pxedrv, pxe, ( ( bus << 8 ) | devfn ), -1U, -1U );
|
|
308
|
+}
|