2 * Copyright (C) 2010 Piotr JaroszyĆski <p.jaroszynski@gmail.com>
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.
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.
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 St, Fifth Floor, Boston, MA 02110-1301 USA.
19 FILE_LICENCE(GPL2_OR_LATER
);
23 * Linux root_device and root_driver.
29 #include <ipxe/linux.h>
30 #include <ipxe/malloc.h>
31 #include <ipxe/settings.h>
33 LIST_HEAD(linux_device_requests
);
34 LIST_HEAD(linux_global_settings
);
36 /** Go over the device requests looking for a matching linux driver to handle them. */
37 static int linux_probe(struct root_device
*rootdev
)
39 struct linux_device_request
*request
;
40 struct linux_driver
*driver
;
41 struct linux_device
*device
= NULL
;
44 /* Apply global settings */
45 linux_apply_settings(&linux_global_settings
, NULL
);
47 list_for_each_entry(request
, &linux_device_requests
, list
) {
49 device
= zalloc(sizeof(*device
));
56 for_each_table_entry(driver
, LINUX_DRIVERS
) {
57 if ((rc
= strcmp(driver
->name
, request
->driver
)) == 0)
62 printf("Linux driver '%s' not found\n", request
->driver
);
66 if (! driver
->can_probe
) {
67 printf("Driver '%s' cannot handle any more devices\n", driver
->name
);
71 /* We found a matching driver so add the device to the hierarchy */
72 list_add(&device
->dev
.siblings
, &rootdev
->dev
.children
);
73 device
->dev
.parent
= &rootdev
->dev
;
74 INIT_LIST_HEAD(&device
->dev
.children
);
76 if (driver
->probe(device
, request
) == 0) {
77 device
->driver
= driver
;
78 device
->dev
.driver_name
= driver
->name
;
79 /* Driver handled the device so release ownership */
82 /* Driver failed to handle the device so remove it from the hierarchy
83 * and reuse the object */
84 list_del(&device
->dev
.siblings
);
93 /** Remove all the linux devices registered in probe() */
94 static void linux_remove(struct root_device
*rootdev
)
96 struct linux_device
*device
;
97 struct linux_device
*tmp
;
99 list_for_each_entry_safe(device
, tmp
, &rootdev
->dev
.children
, dev
.siblings
) {
100 list_del(&device
->dev
.siblings
);
101 device
->driver
->remove(device
);
106 /** Linux root driver */
107 static struct root_driver linux_root_driver
= {
108 .probe
= linux_probe
,
109 .remove
= linux_remove
,
112 /** Linux root device */
113 struct root_device linux_root_device __root_device
= {
114 .dev
= { .name
= "linux" },
115 .driver
= &linux_root_driver
,
118 struct linux_setting
*linux_find_setting(char *name
, struct list_head
*settings
)
120 struct linux_setting
*setting
;
121 struct linux_setting
*result
= NULL
;
123 /* Find the last occurrence of a setting with the specified name */
124 list_for_each_entry(setting
, settings
, list
) {
125 if (strcmp(setting
->name
, name
) == 0) {
134 * Apply Linux command-line settings
136 * @v list List of command-line settings
137 * @v settings Settings block
139 void linux_apply_settings ( struct list_head
*list
,
140 struct settings
*settings
) {
141 struct linux_setting
*lsetting
;
142 struct settings
*ignore
;
143 struct setting setting
;
146 list_for_each_entry ( lsetting
, list
, list
) {
148 /* Skip already applied settings */
149 if ( lsetting
->applied
)
152 /* Parse setting name */
153 if ( ( rc
= parse_setting_name ( lsetting
->name
,
154 find_child_settings
, &ignore
,
155 &setting
) ) != 0 ) {
156 DBGC ( settings
, "Linux cannot parse %s: %s\n",
157 lsetting
->name
, strerror ( rc
) );
161 /* Apply default type if not specified */
162 if ( ! setting
.type
)
163 setting
.type
= &setting_type_string
;
166 if ( ( rc
= storef_setting ( settings
, &setting
,
167 lsetting
->value
) ) != 0 ) {
168 DBGC ( settings
, "Linux cannot set %s=\"%s\": %s\n",
169 lsetting
->name
, lsetting
->value
,
174 /* Mark setting as applied */
175 lsetting
->applied
= 1;