iPXE
undionly.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <ipxe/device.h>
31 #include <ipxe/init.h>
32 #include <ipxe/pci.h>
33 #include <undi.h>
34 #include <undinet.h>
35 #include <undipreload.h>
36 
37 /** @file
38  *
39  * "Pure" UNDI driver
40  *
41  * This is the UNDI driver without explicit support for PCI or any
42  * other bus type. It is capable only of using the preloaded UNDI
43  * device. It must not be combined in an image with any other
44  * drivers.
45  *
46  * If you want a PXE-loadable image that contains only the UNDI
47  * driver, build "bin/undionly.kpxe".
48  *
49  * If you want any other image format, or any other drivers in
50  * addition to the UNDI driver, build e.g. "bin/undi.dsk".
51  */
52 
53 /** UNDI root bus device */
54 static struct device undibus_dev;
55 
56 /**
57  * Probe UNDI root bus
58  *
59  * @v rootdev UNDI bus root device
60  *
61  * Scans the UNDI bus for devices and registers all devices it can
62  * find.
63  */
64 static int undibus_probe ( struct root_device *rootdev ) {
65  struct undi_device *undi = &preloaded_undi;
66  struct device *dev = &undibus_dev;
67  int rc;
68 
69  /* Check for a valie preloaded UNDI device */
70  if ( ! undi->entry.segment ) {
71  DBG ( "No preloaded UNDI device found!\n" );
72  return -ENODEV;
73  }
74 
75  /* Add to device hierarchy */
76  dev->driver_name = "undionly";
77  if ( undi->pci_busdevfn != UNDI_NO_PCI_BUSDEVFN ) {
78  dev->desc.bus_type = BUS_TYPE_PCI;
79  dev->desc.location = undi->pci_busdevfn;
80  dev->desc.vendor = undi->pci_vendor;
81  dev->desc.device = undi->pci_device;
82  snprintf ( dev->name, sizeof ( dev->name ),
83  "0000:%02x:%02x.%x", PCI_BUS ( undi->pci_busdevfn ),
84  PCI_SLOT ( undi->pci_busdevfn ),
85  PCI_FUNC ( undi->pci_busdevfn ) );
86  } else if ( undi->isapnp_csn != UNDI_NO_ISAPNP_CSN ) {
88  snprintf ( dev->name, sizeof ( dev->name ), "ISAPNP" );
89  }
90  dev->parent = &rootdev->dev;
91  list_add ( &dev->siblings, &rootdev->dev.children);
92  INIT_LIST_HEAD ( &dev->children );
93 
94  /* Create network device */
95  if ( ( rc = undinet_probe ( undi, dev ) ) != 0 )
96  goto err;
97 
98  return 0;
99 
100  err:
101  list_del ( &dev->siblings );
102  return rc;
103 }
104 
105 /**
106  * Remove UNDI root bus
107  *
108  * @v rootdev UNDI bus root device
109  */
110 static void undibus_remove ( struct root_device *rootdev __unused ) {
111  struct undi_device *undi = &preloaded_undi;
112  struct device *dev = &undibus_dev;
113 
114  undinet_remove ( undi );
115  list_del ( &dev->siblings );
116 }
117 
118 /** UNDI bus root device driver */
119 static struct root_driver undi_root_driver = {
120  .probe = undibus_probe,
121  .remove = undibus_remove,
122 };
123 
124 /** UNDI bus root device */
125 struct root_device undi_root_device __root_device = {
126  .dev = { .name = "UNDI" },
127  .driver = &undi_root_driver,
128 };
129 
130 /**
131  * Prepare for exit
132  *
133  * @v booting System is shutting down for OS boot
134  */
135 static void undionly_shutdown ( int booting ) {
136  /* If we are shutting down to boot an OS, clear the "keep PXE
137  * stack" flag.
138  */
139  if ( booting )
141 }
142 
143 struct startup_fn startup_undionly __startup_fn ( STARTUP_LATE ) = {
144  .name = "undionly",
145  .shutdown = undionly_shutdown,
146 };
#define PCI_FUNC(busdevfn)
Definition: pci.h:281
#define PCI_BUS(busdevfn)
Definition: pci.h:279
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
static int undibus_probe(struct root_device *rootdev)
Probe UNDI root bus.
Definition: undionly.c:64
int undinet_probe(struct undi_device *undi, struct device *dev)
Probe UNDI device.
Definition: undinet.c:888
char name[40]
Name.
Definition: device.h:75
A root device.
Definition: device.h:94
static void undionly_shutdown(int booting)
Prepare for exit.
Definition: undionly.c:135
#define UNDI_NO_ISAPNP_CSN
ISAPnP card select number field is invalid.
Definition: undi.h:90
static void undibus_remove(struct root_device *rootdev __unused)
Remove UNDI root bus.
Definition: undionly.c:110
UNDI network device driver.
UNDI driver.
struct device dev
Device chain.
Definition: device.h:99
const char * name
Definition: init.h:42
unsigned int vendor
Vendor ID.
Definition: device.h:31
struct device * parent
Bus device.
Definition: device.h:85
#define STARTUP_LATE
Late startup.
Definition: init.h:64
void undinet_remove(struct undi_device *undi)
Remove UNDI device.
Definition: undinet.c:1042
UINT16_t isapnp_csn
ISAPnP card select number, or UNDI_NO_ISAPNP_CSN.
Definition: undi.h:36
static struct device undibus_dev
UNDI root bus device.
Definition: undionly.c:54
A startup/shutdown function.
Definition: init.h:41
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
A hardware device.
Definition: device.h:73
#define BUS_TYPE_PCI
PCI bus type.
Definition: device.h:43
Preloaded UNDI stack.
#define preloaded_undi
Definition: undipreload.h:16
#define UNDI_FL_KEEP_ALL
UNDI flag: keep stack resident.
Definition: undi.h:102
const char * driver_name
Driver name.
Definition: device.h:77
unsigned int location
Location.
Definition: device.h:29
SEGOFF16_t entry
Entry point.
Definition: undi.h:28
UINT16_t pci_device
PCI device ID.
Definition: undi.h:48
#define PCI_SLOT(busdevfn)
Definition: pci.h:280
PCI bus.
struct list_head siblings
Devices on the same bus.
Definition: device.h:81
UINT16_t pci_vendor
PCI vendor ID.
Definition: undi.h:43
A root device driver.
Definition: device.h:107
#define ENODEV
No such device.
Definition: errno.h:509
#define UNDI_NO_PCI_BUSDEVFN
PCI bus:dev.fn field is invalid.
Definition: undi.h:87
struct startup_fn startup_undionly __startup_fn(STARTUP_LATE)
An UNDI device.
Definition: undi.h:22
int(* probe)(struct root_device *rootdev)
Add root device.
Definition: device.h:116
UINT16_t pci_busdevfn
PCI bus:dev.fn, or UNDI_NO_PCI_BUSDEVFN.
Definition: undi.h:34
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
unsigned int bus_type
Bus type.
Definition: device.h:24
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
unsigned int device
Device ID.
Definition: device.h:33
struct root_device undi_root_device __root_device
UNDI bus root device.
Definition: undionly.c:125
struct list_head children
Devices attached to this device.
Definition: device.h:83
struct device_description desc
Device description.
Definition: device.h:79
Device model.
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static struct root_driver undi_root_driver
UNDI bus root device driver.
Definition: undionly.c:119
String functions.
#define BUS_TYPE_ISAPNP
ISAPnP bus type.
Definition: device.h:46