|
|
1.1 root 1: /*
2: * Copyright (C) 2010 Piotr JaroszyĆski <[email protected]>
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 St, Fifth Floor, Boston, MA 02110-1301 USA.
17: */
18:
19: FILE_LICENCE(GPL2_OR_LATER);
20:
21: /** @file
22: *
23: * Linux root_device and root_driver.
24: */
25:
26: #include <errno.h>
27: #include <string.h>
28: #include <stdio.h>
29: #include <ipxe/linux.h>
30: #include <ipxe/malloc.h>
31: #include <ipxe/settings.h>
32:
33: LIST_HEAD(linux_device_requests);
34: LIST_HEAD(linux_global_settings);
35:
36: /** Go over the device requests looking for a matching linux driver to handle them. */
37: static int linux_probe(struct root_device *rootdev)
38: {
39: struct linux_device_request *request;
40: struct linux_driver *driver;
41: struct linux_device *device = NULL;
42: int rc;
43:
44: /* Apply global settings */
45: linux_apply_settings(&linux_global_settings, NULL);
46:
47: list_for_each_entry(request, &linux_device_requests, list) {
48: if (! device)
49: device = zalloc(sizeof(*device));
50:
51: if (! device)
52: return -ENOMEM;
53:
54: rc = 1;
55:
56: for_each_table_entry(driver, LINUX_DRIVERS) {
57: if ((rc = strcmp(driver->name, request->driver)) == 0)
58: break;
59: }
60:
61: if (rc != 0) {
62: printf("Linux driver '%s' not found\n", request->driver);
63: continue;
64: }
65:
66: if (! driver->can_probe) {
67: printf("Driver '%s' cannot handle any more devices\n", driver->name);
68: continue;
69: }
70:
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);
75:
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 */
80: device = NULL;
81: } else {
82: /* Driver failed to handle the device so remove it from the hierarchy
83: * and reuse the object */
84: list_del(&device->dev.siblings);
85: }
86: };
87:
88: free(device);
89:
90: return 0;
91: }
92:
93: /** Remove all the linux devices registered in probe() */
94: static void linux_remove(struct root_device *rootdev)
95: {
96: struct linux_device *device;
97: struct linux_device *tmp;
98:
99: list_for_each_entry_safe(device, tmp, &rootdev->dev.children, dev.siblings) {
100: list_del(&device->dev.siblings);
101: device->driver->remove(device);
102: free(device);
103: }
104: }
105:
106: /** Linux root driver */
107: static struct root_driver linux_root_driver = {
108: .probe = linux_probe,
109: .remove = linux_remove,
110: };
111:
112: /** Linux root device */
113: struct root_device linux_root_device __root_device = {
114: .dev = { .name = "linux" },
115: .driver = &linux_root_driver,
116: };
117:
118: struct linux_setting *linux_find_setting(char *name, struct list_head *settings)
119: {
120: struct linux_setting *setting;
121: struct linux_setting *result = NULL;
122:
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) {
126: result = setting;
127: }
128: }
129:
130: return result;
131: }
132:
133: void linux_apply_settings(struct list_head *new_settings, struct settings *settings_block)
134: {
135: struct linux_setting *setting;
136: int rc;
137:
138: list_for_each_entry(setting, new_settings, list) {
139: /* Skip already applied settings */
140: if (setting->applied)
141: continue;
142:
143: struct setting *s = find_setting(setting->name);
144: if (s) {
145: rc = storef_setting(settings_block, find_setting(setting->name), setting->value);
146: if (rc != 0)
147: DBG("linux storing setting '%s' = '%s' failed\n", setting->name, setting->value);
148: setting->applied = 1;
149: } else {
150: DBG("linux unknown setting '%s'\n", setting->name);
151: }
152: }
153: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.