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"
29 extern char bootdevice[1024];
31 /* This function follows the device path in the devtree and separates
32 the device name, partition number, and other datas (mostly file name)
33 the string passed in parameters is changed since 0 are put in place
34 of some separators to terminate the various strings
37 parse_device_path(char *of_device, char **file_spec, int *partition)
46 p = strchr(of_device, ':');
53 while(*p && *p != ',') {
63 *partition = simple_strtol(last, NULL, 10);
73 validate_fspec( struct boot_fspec_t* spec,
78 spec->file = spec->dev;
82 spec->part = default_part;
84 spec->dev = default_device;
87 else if (spec->file[0] == ',')
94 file_block_open( struct boot_file_t* file,
96 const char* file_name,
99 struct partition_t* parts;
100 struct partition_t* p;
101 struct partition_t* found;
103 parts = partitions_lookup(dev_name);
108 prom_printf("partitions:\n");
110 prom_printf("no partitions found.\n");
112 for (p = parts; p && !found; p=p->next) {
114 prom_printf("number: %02d, start: 0x%08lx, length: 0x%08lx\n",
115 p->part_number, p->part_start, p->part_size );
117 if (partition == -1) {
118 file->fs = fs_open( file, dev_name, p, file_name );
119 if (file->fs != NULL)
122 if ((partition >= 0) && (partition == p->part_number))
126 prom_printf(" (match)\n");
130 /* Note: we don't skip when found is NULL since we can, in some
131 * cases, let OF figure out a default partition.
133 DEBUG_F( "Using OF defaults.. (found = 0x%x)\n", found );
134 file->fs = fs_open( file, dev_name, found, file_name );
138 partitions_free(parts);
140 return file->fs ? FILE_ERR_OK : FILE_ERR_NOTFOUND;
144 file_net_open( struct boot_file_t* file,
145 const char* dev_name,
146 const char* file_name)
148 file->fs = fs_of_netboot;
149 return fs_of_netboot->open(file, dev_name, NULL, file_name);
153 default_read( struct boot_file_t* file,
157 prom_printf("WARNING ! default_read called !\n");
162 default_seek( struct boot_file_t* file,
165 prom_printf("WARNING ! default_seek called !\n");
170 default_close( struct boot_file_t* file)
172 prom_printf("WARNING ! default_close called !\n");
176 static struct fs_t fs_default =
186 int open_file( const struct boot_fspec_t* spec,
187 struct boot_file_t* file)
189 static char temp[1024];
190 static char temps[64];
192 char *file_name = NULL;
197 memset(file, 0, sizeof(struct boot_file_t*));
198 file->fs = &fs_default;
200 /* Lookup the OF device path */
201 /* First, see if a device was specified for the kernel
202 * if not, we hope that the user wants a kernel on the same
203 * drive and partition as yaboot itself */
205 strcpy(spec->dev, bootdevice);
206 strncpy(temp,spec->dev,1024);
207 dev_name = parse_device_path(temp, &file_name, &partition);
208 if (file_name == NULL)
209 file_name = (char *)spec->file;
210 if (file_name == NULL) {
211 prom_printf("booting without a file name not yet supported !\n");
212 return FILE_ERR_NOTFOUND;
215 partition = spec->part;
218 prom_printf("dev_path = %s\nfile_name = %s\npartition = %d\n",
219 dev_name, file_name, partition);
221 /* Find OF device phandle */
222 dev = prom_finddevice(dev_name);
223 if (dev == PROM_INVALID_HANDLE) {
224 prom_printf("device not found !\n");
225 return FILE_ERR_NOTFOUND;
228 prom_printf("dev_phandle = %08lx\n", dev);
230 /* Check the kind of device */
231 result = prom_getprop(dev, "device_type", temps, 63);
233 prom_printf("can't get <device_type> for device\n");
234 return FILE_ERR_NOTFOUND;
237 if (!strcmp(temps, "block"))
238 file->device_kind = FILE_DEVICE_BLOCK;
239 else if (!strcmp(temps, "network"))
240 file->device_kind = FILE_DEVICE_NET;
242 prom_printf("Unkown device type <%s>\n", temps);
243 return FILE_ERR_NOTFOUND;
246 switch(file->device_kind) {
247 case FILE_DEVICE_BLOCK:
249 prom_printf("device is a block device\n");
251 return file_block_open(file, dev_name, file_name, partition);
252 case FILE_DEVICE_NET:
254 prom_printf("device is a network device\n");
256 return file_net_open(file, dev_name, file_name);