3 Copyright (C) 1999 Benjamin Herrenschmidt
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
26 #include "partition.h"
30 extern char bootdevice[1024];
32 /* This function follows the device path in the devtree and separates
33 the device name, partition number, and other datas (mostly file name)
34 the string passed in parameters is changed since 0 are put in place
35 of some separators to terminate the various strings
39 parse_device_path(char *imagepath, char *defdevice, int defpart,
40 char *deffile, struct boot_fspec_t *result)
43 char *ipath = strdup(imagepath);
44 char *defdev = strdup(defdevice);
50 if (!strstr(defdev, "ethernet") && !strstr(defdev, "enet")) {
51 if ((ptr = strchr(defdev, ':')) != NULL)
52 *ptr = 0; /* remove trailing : from defdevice if necessary */
58 if ((ptr = strrchr(ipath, ',')) != NULL) {
59 result->file = strdup(ptr+1);
60 /* Trim the filename off */
64 if (strstr(ipath, "ethernet") || strstr(ipath, "enet"))
65 result->dev = strdup(ipath);
66 else if ((ptr = strchr(ipath, ':')) != NULL) {
68 result->dev = strdup(ipath);
70 result->part = simple_strtol(ptr+1, NULL, 10);
71 } else if (strlen(ipath)) {
72 result->file = strdup(ipath);
79 result->dev = strdup(defdev);
82 result->part = defpart;
85 result->file = strdup(deffile);
92 parse_device_path(char *of_device, char **file_spec, int *partition)
101 DEBUG_F("of_device before parsing: %s\n", of_device);
102 p = strchr(of_device, ':');
103 DEBUG_F("of_device after parsing: %s\n", p);
105 if (!p) { /* if null terminated we are finished */
106 DEBUG_F("of_device: %s\n", of_device);
109 #if 0 /* this is broken crap, breaks netboot entirely */
110 else if (strstr(of_device, "ethernet") != NULL)
111 p = strchr(of_device, ','); /* skip over ip all the way to the ',' */
112 else if (strstr(of_device, "enet") != NULL)
113 p = strchr(of_device, ','); /* skip over ip all the way to the ',' */
116 last = ++p; /* sets to start of second part */
117 while(*p && *p != ',') {
127 *partition = simple_strtol(last, NULL, 10);
132 DEBUG_F("of_device: %s\n", of_device);
133 strcat(of_device, ":");
134 DEBUG_F("of_device after strcat: %s\n", of_device);
139 validate_fspec( struct boot_fspec_t* spec,
140 char* default_device,
144 spec->file = spec->dev;
147 if (spec->part == -1)
148 spec->part = default_part;
150 spec->dev = default_device;
152 return FILE_BAD_PATH;
153 else if (spec->file[0] == ',')
162 file_block_open( struct boot_file_t* file,
163 const char* dev_name,
164 const char* file_name,
167 struct partition_t* parts;
168 struct partition_t* p;
169 struct partition_t* found;
171 parts = partitions_lookup(dev_name);
176 prom_printf("partitions:\n");
178 prom_printf("no partitions found.\n");
180 for (p = parts; p && !found; p=p->next) {
181 DEBUG_F("number: %02d, start: 0x%08lx, length: 0x%08lx\n",
182 p->part_number, p->part_start, p->part_size );
183 if (partition == -1) {
184 file->fs = fs_open( file, dev_name, p, file_name );
185 if (file->fs != NULL)
188 if ((partition >= 0) && (partition == p->part_number))
192 prom_printf(" (match)\n");
196 /* Note: we don't skip when found is NULL since we can, in some
197 * cases, let OF figure out a default partition.
199 DEBUG_F( "Using OF defaults.. (found = %p)\n", found );
200 file->fs = fs_open( file, dev_name, found, file_name );
204 partitions_free(parts);
210 file_net_open( struct boot_file_t* file,
211 const char* dev_name,
212 const char* file_name)
214 file->fs = fs_of_netboot;
215 return fs_of_netboot->open(file, dev_name, NULL, file_name);
219 default_read( struct boot_file_t* file,
223 prom_printf("WARNING ! default_read called !\n");
228 default_seek( struct boot_file_t* file,
231 prom_printf("WARNING ! default_seek called !\n");
236 default_close( struct boot_file_t* file)
238 prom_printf("WARNING ! default_close called !\n");
242 static struct fs_t fs_default =
252 int open_file( const struct boot_fspec_t* spec,
253 struct boot_file_t* file)
255 // static char temp[1024];
256 static char temps[64];
258 // char *file_name = NULL;
263 memset(file, 0, sizeof(struct boot_file_t*));
264 file->fs = &fs_default;
266 /* Lookup the OF device path */
267 /* First, see if a device was specified for the kernel
268 * if not, we hope that the user wants a kernel on the same
269 * drive and partition as yaboot itself */
270 #if 0 /* this is crap */
272 strcpy(spec->dev, bootdevice);
273 strncpy(temp,spec->dev,1024);
274 dev_name = parse_device_path(temp, &file_name, &partition);
275 if (file_name == NULL)
276 file_name = (char *)spec->file;
277 if (file_name == NULL) {
278 prom_printf("Configuration error: null filename\n");
279 return FILE_ERR_NOTFOUND;
283 partition = spec->part;
286 DEBUG_F("dev_path = %s\nfile_name = %s\npartition = %d\n",
287 spec->dev, spec->file, partition);
289 /* Find OF device phandle */
290 dev = prom_finddevice(spec->dev);
291 if (dev == PROM_INVALID_HANDLE) {
292 return FILE_ERR_BADDEV;
295 DEBUG_F("dev_phandle = %p\n", dev);
297 /* Check the kind of device */
298 result = prom_getprop(dev, "device_type", temps, 63);
300 prom_printf("can't get <device_type> for device\n");
301 return FILE_ERR_BADDEV;
304 if (!strcmp(temps, "block"))
305 file->device_kind = FILE_DEVICE_BLOCK;
306 else if (!strcmp(temps, "network"))
307 file->device_kind = FILE_DEVICE_NET;
309 prom_printf("Unkown device type <%s>\n", temps);
310 return FILE_ERR_BADDEV;
313 switch(file->device_kind) {
314 case FILE_DEVICE_BLOCK:
315 DEBUG_F("device is a block device\n");
316 return file_block_open(file, spec->dev, spec->file, partition);
317 case FILE_DEVICE_NET:
318 DEBUG_F("device is a network device\n");
319 return file_net_open(file, spec->dev, spec->file);
326 * c-file-style: "K&R"