X-Git-Url: http://git.ozlabs.org/?p=yaboot.git;a=blobdiff_plain;f=second%2Ffile.c;h=a52b664e8900c6e789764c696f5d4e61ab9fab0d;hp=726f313b1de2672e66f3ecbad69fcfc4a7d844f9;hb=3cbe90093acba116c5fc46beaf50f74c7c8a1b69;hpb=f4ebbd9f7ea23e3f0fcbe098754580c220894628 diff --git a/second/file.c b/second/file.c index 726f313..a52b664 100644 --- a/second/file.c +++ b/second/file.c @@ -1,20 +1,28 @@ -/* File related stuff - - Copyright (C) 1999 Benjamin Herrenschmidt - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + * file.c - Filesystem related interfaces + * + * Copyright (C) 2001, 2002 Ethan Benson + * + * parse_device_path() + * + * Copyright (C) 2001 Colin Walters + * + * Copyright (C) 1999 Benjamin Herrenschmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ #include "ctype.h" #include "types.h" @@ -25,128 +33,592 @@ #include "string.h" #include "partition.h" #include "fs.h" +#include "errors.h" +#include "debug.h" -extern char bootdevice[1024]; +extern char bootdevice[]; -/* This function follows the device path in the devtree and separates - the device name, partition number, and other datas (mostly file name) - the string passed in parameters is changed since 0 are put in place - of some separators to terminate the various strings +/* Convert __u32 into std, dotted quad string, leaks like a sive :( */ +static char * +ipv4_to_str(__u32 ip) +{ + char *buf = malloc(sizeof("000.000.000.000")); + + sprintf(buf,"%u.%u.%u.%u", + (ip & 0xff000000) >> 24, (ip & 0x00ff0000) >> 16, + (ip & 0x0000ff00) >> 8, (ip & 0x000000ff)); + + return buf; +} + +/* Ensure the string arg is a plausible IPv4 address */ +static char * is_valid_ipv4_str(char *str) +{ + int i; + long tmp; + __u32 ip = 0; + char *ptr=str, *endptr; + + if (str == NULL) + return NULL; + + for (i=0; i<4; i++, ptr = ++endptr) { + tmp = strtol(ptr, &endptr, 10); + if ((tmp & 0xff) != tmp) + return NULL; + + /* If we reach the end of the string but we're not in the 4th octet + * we have an invalid IP */ + if (*endptr == '\x0' && i!=3) + return NULL; + + /* If we have anything other than a NULL or '.' we have an invlaid + * IP */ + if (*endptr != '\x0' && *endptr != '.') + return NULL; + + ip += (tmp << (24-(i*8))); + } + + if (ip == 0 || ip == ~0u) + return NULL; + + return str; +} + + +/* + * Copy the string from source to dest till newline or comma(,) is seen + * in the source. + * Move source and dest pointers respectively. + * Returns pointer to the start of the string that has just been copied. + */ +static char * +scopy(char **dest, char **source) +{ + char *ret = *dest; + + if (!**source) + return NULL; + + while (**source != ',' && **source != '\0') + *(*dest)++ = *(*source)++; + if (**source != '\0') + *(*source)++; + **dest = '\0'; + *(*dest)++; + return ret; +} + +/* + * Extract all the ipv4 arguments from the bootpath provided and fill result + * Returns 1 on success, 0 on failure. + */ +static int +extract_ipv4_args(char *imagepath, struct boot_fspec_t *result) +{ + char *tmp, *args, *str, *start; + + args = strrchr(imagepath, ':'); + if (!args) + return 1; + + start = args; /* used to see if we read any optional parameters */ + + /* The obp-tftp device arguments should be at the end of + * the argument list. Skip over any extra arguments (promiscuous, + * speed, duplex, bootp, rarp). + */ + + tmp = strstr(args, "promiscuous"); + if (tmp && tmp > args) + args = tmp + strlen("promiscuous"); + + tmp = strstr(args, "speed="); + if (tmp && tmp > args) + args = tmp + strlen("speed="); + + tmp = strstr(args, "duplex="); + if (tmp && tmp > args) + args = tmp + strlen("duplex="); + + tmp = strstr(args, "bootp"); + if (tmp && tmp > args) + args = tmp + strlen("bootp"); + + tmp = strstr(args, "rarp"); + if (tmp && tmp > args) + args = tmp + strlen("rarp"); + + if (args != start) /* we read some parameters, so go past the next comma(,) */ + args = strchr(args, ','); + if (!args) + return 1; + + str = malloc(strlen(args) + 1); /*long enough to hold all strings */ + if (!str) + return 0; + + if (args[-1] != ':') + args++; /* If comma(,) is not immediately followed by ':' then go past the , */ + + /* + * read the arguments in order: siaddr,filename,ciaddr,giaddr, + * bootp-retries,tftp-retries,addl_prameters + */ + result->siaddr = is_valid_ipv4_str(scopy(&str, &args)); + result->file = scopy(&str, &args); + result->ciaddr = is_valid_ipv4_str(scopy(&str, &args)); + result->giaddr = is_valid_ipv4_str(scopy(&str, &args)); + result->bootp_retries = scopy(&str, &args); + result->tftp_retries = scopy(&str, &args); + result->subnetmask = is_valid_ipv4_str(scopy(&str, &args)); + if (*args) { + result->addl_params = strdup(args); + if (!result->addl_params) + return 0; + } + return 1; +} + +/* DHCP options */ +enum dhcp_options { + DHCP_PAD = 0, + DHCP_NETMASK = 1, + DHCP_ROUTERS = 3, + DHCP_END = 255, +}; + +#define DHCP_COOKIE 0x63825363 +#define DHCP_COOKIE_SIZE 4 + +/* + * Process the bootp reply packet's vendor extensions. + * Vendor extensions are detailed in: http://www.faqs.org/rfcs/rfc1084.html + */ +static void +extract_vendor_options(struct bootp_packet *packet, struct boot_fspec_t *result) +{ + int i = 0; + __u32 cookie; + __u8 *options = &packet->options[0]; + + memcpy(&cookie, &options[i], DHCP_COOKIE_SIZE); + + if (cookie != DHCP_COOKIE) { + prom_printf("EEEK! cookie is fubar got %08x expected %08x\n", + cookie, DHCP_COOKIE); + return; + } + + i += DHCP_COOKIE_SIZE; + + /* FIXME: It may be possible to run off the end of a packet here /if/ + * it's malformed. :( */ + while (options[i] != DHCP_END) { + __u8 tag = options[i++], len; + __u32 value = 0; + + if (tag == DHCP_PAD) + continue; + + len = options[i++]; + /* Clamp the maxium length of the memcpy() to the right size for + * value. */ + if (len > sizeof(value)) + memcpy(&value, &options[i], sizeof(value)); + else + memcpy(&value, &options[i], len); + +#if DEBUG +{ + DEBUG_F("tag=%2d, len=%2d, data=", tag, len); + int j; + for (j=0; jsubnetmask == NULL || + *(result->subnetmask) == '\x0') && value != 0) { + result->subnetmask = ipv4_to_str(value); + DEBUG_F("Storing %s as subnetmask from options\n", + result->subnetmask); + } + break; + case DHCP_ROUTERS: + if ((result->giaddr == NULL || *(result->giaddr) == '\x0') + && value != 0) { + result->giaddr = ipv4_to_str(value); + DEBUG_F("Storing %s as gateway from options\n", + result->giaddr); + } + break; + } + i += len; + } +} + +/* + * Check netinfo for ipv4 parameters and add them to the fspec iff the + * fspec has no existing value. + */ +static void +extract_netinfo_args(struct boot_fspec_t *result) +{ + struct bootp_packet *packet; + + /* Check to see if we can get the [scyg]iaddr fields from netinfo */ + packet = prom_get_netinfo(); + if (!packet) + return; + + DEBUG_F("We have a boot packet\n"); + DEBUG_F(" siaddr = <%x>\n", packet->siaddr); + DEBUG_F(" ciaddr = <%x>\n", packet->ciaddr); + DEBUG_F(" yiaddr = <%x>\n", packet->yiaddr); + DEBUG_F(" giaddr = <%x>\n", packet->giaddr); + + /* Try to fallback to yiaddr if ciaddr is empty. Broken? */ + if (packet->ciaddr == 0 && packet->yiaddr != 0) + packet->ciaddr = packet->yiaddr; + + if ((result->siaddr == NULL || *(result->siaddr) == '\x0') + && packet->siaddr != 0) + result->siaddr = ipv4_to_str(packet->siaddr); + if ((result->ciaddr == NULL || *(result->ciaddr) == '\x0') + && packet->ciaddr != 0) + result->ciaddr = ipv4_to_str(packet->ciaddr); + if ((result->giaddr == NULL || *(result->giaddr) == '\x0') + && packet->giaddr != 0) + result->giaddr = ipv4_to_str(packet->giaddr); + + extract_vendor_options(packet, result); + + /* FIXME: Yck! if we /still/ do not have a gateway then "cheat" and use + * the server. This will be okay if the client and server are on + * the same IP network, if not then lets hope the server does ICMP + * redirections */ + if (result->giaddr == NULL) { + result->giaddr = ipv4_to_str(packet->siaddr); + DEBUG_F("Forcing giaddr to siaddr <%s>\n", result->giaddr); + } +} + +/* + * Extract all the ipv6 arguments from the bootpath provided and fill result + * Syntax: ipv6,[dhcpv6[=diaddr,]]ciaddr=c_iaddr,giaddr=g_iaddr,siaddr=s_iaddr, + * filename=file_name,tftp-retries=tftp_retries,blksize=block_size + * Returns 1 on success, 0 on failure. */ -char * -parse_device_path(char *of_device, char **file_spec, int *partition) +static int +extract_ipv6_args(char *imagepath, struct boot_fspec_t *result) { - char *p, *last; - - if (file_spec) - *file_spec = NULL; - if (partition) - *partition = -1; - - p = strchr(of_device, ':'); - if (p) - *p = 0; - else - return of_device; - - last = ++p; - while(*p && *p != ',') { - if (!isdigit (*p)) { - p = last; - break; - } - ++p; - } - if (p != last) { - *(p++) = 0; - if (partition) - *partition = simple_strtol(last, NULL, 10); - } - if (*p && file_spec) - *file_spec = p; - - return of_device; + char *str, *tmp; + int total_len; + + result->is_ipv6 = 1; + + /* Just allocate the max required size */ + total_len = strlen(imagepath) + 1; + str = malloc(total_len); + if (!str) + return 0; + + if ((tmp = strstr(imagepath, "dhcpv6=")) != NULL) + result->dhcpv6 = scopy(&str, &tmp); + + if ((tmp = strstr(imagepath, "ciaddr=")) != NULL) + result->ciaddr = scopy(&str, &tmp); + + if ((tmp = strstr(imagepath, "giaddr=")) != NULL) + result->giaddr = scopy(&str, &tmp); + if ((tmp = strstr(imagepath, "siaddr=")) != NULL) + result->siaddr = scopy(&str, &tmp); + + if ((tmp = strstr(imagepath, "filename=")) != NULL) + result->file = scopy(&str, &tmp); + + if ((tmp = strstr(imagepath, "tftp-retries=")) != NULL) + result->tftp_retries = scopy(&str, &tmp); + + if ((tmp = strstr(imagepath, "blksize=")) != NULL) + result->blksize = scopy(&str, &tmp); + + return 1; } +/* + * Extract all the arguments provided in the imagepath and fill it in result. + * Returns 1 on success, 0 on failure. + */ +static int +extract_netboot_args(char *imagepath, struct boot_fspec_t *result) +{ + int ret; + + DEBUG_F("imagepath = %s\n", imagepath); + + if (!imagepath) + return 1; + + if (strstr(imagepath, TOK_IPV6)) + ret = extract_ipv6_args(imagepath, result); + else + ret = extract_ipv4_args(imagepath, result); + extract_netinfo_args(result); + + DEBUG_F("ipv6 = <%d>\n", result->is_ipv6); + DEBUG_F("siaddr = <%s>\n", result->siaddr); + DEBUG_F("file = <%s>\n", result->file); + DEBUG_F("ciaddr = <%s>\n", result->ciaddr); + DEBUG_F("giaddr = <%s>\n", result->giaddr); + DEBUG_F("bootp_retries = <%s>\n", result->bootp_retries); + DEBUG_F("tftp_retries = <%s>\n", result->tftp_retries); + DEBUG_F("addl_params = <%s>\n", result->addl_params); + DEBUG_F("dhcpv6 = <%s>\n", result->dhcpv6); + DEBUG_F("blksize = <%s>\n", result->blksize); + + return ret; +} + +static char *netdev_path_to_dev(const char *path) +{ + char *dev, *tmp; + size_t len; + + DEBUG_F("path = %s\n", path); + + if (!path) + return NULL; + + tmp = strchr(path, ':'); + if (!tmp) + return strdup(path); + tmp++; + + len = tmp - path + 1; + + dev = malloc(len); + if (dev) { + strncpy(dev, path, len); + dev[len - 1] = '\0'; + } + return dev; +} + +/* This function follows the device path in the devtree and separates + the device name, partition number, and other datas (mostly file name) + the string passed in parameters is changed since 0 are put in place + of some separators to terminate the various strings. + + when a default device is supplied imagepath will be assumed to be a + plain filename unless it contains a : otherwise if defaultdev is + NULL imagepath will be assumed to be a device path. + + returns 1 on success 0 on failure. + + Supported examples: + - /pci@80000000/pci-bridge@d/ADPT,2930CU@2/@1:4 + - /pci@80000000/pci-bridge@d/ADPT,2930CU@2/@1:4,/boot/vmlinux + - hd:3,/boot/vmlinux + - enet:10.0.0.1,/tftpboot/vmlinux + - enet:,/tftpboot/vmlinux + - enet:bootp + - enet:0 + - arguments for obp-tftp open as specified in section 4.1 of + http://playground.sun.com/1275/practice/obp-tftp/tftp1_0.pdf + [bootp,]siaddr,filename,ciaddr,giaddr,bootp-retries,tftp-retries + ex: enet:bootp,10.0.0.11,bootme,10.0.0.12,10.0.0.1,5,5 + Supported only if defdevice == NULL + - disc + - any other device path lacking a : + Unsupported examples: + - hd:2,\\:tbxi <- no filename will be detected due to the extra : + - enet:192.168.2.1,bootme,c-iaddr,g-iaddr,subnet-mask,bootp-retries,tftp-retries */ + int -validate_fspec( struct boot_fspec_t* spec, - char* default_device, - int default_part) +parse_device_path(char *imagepath, char *defdevice, int defpart, + char *deffile, struct boot_fspec_t *result) { - if (!spec->file) { - spec->file = spec->dev; - spec->dev = NULL; - } - if (spec->part == -1) - spec->part = default_part; - if (!spec->dev) - spec->dev = default_device; - if (!spec->file) - return FILE_BAD_PATH; - else if (spec->file[0] == ',') - spec->file++; - - return FILE_ERR_OK; + char *ptr; + char *ipath = NULL; + char *defdev = NULL; + int device_kind = -1; + + DEBUG_F("imagepath = %s; defdevice %s; defpart %d, deffile %s\n", + imagepath, defdevice, defpart, deffile); + + result->dev = NULL; + result->part = -1; + result->file = NULL; + + if (!imagepath) + return 0; + + /* + * Do preliminary checking for an iscsi device; it may appear as + * pure a network device (device_type == "network") if this is + * ISWI. This is the case on IBM systems doing an iscsi OFW + * boot. + */ + if (strstr(imagepath, TOK_ISCSI)) { + /* + * get the virtual device information from the + * "nas-bootdevice" property. + */ + if (prom_get_chosen("nas-bootdevice", bootdevice, BOOTDEVSZ)) { + DEBUG_F("reset boot-device to" + " /chosen/nas-bootdevice = %s\n", bootdevice); + device_kind = FILE_DEVICE_ISCSI; + ipath = strdup(bootdevice); + if (!ipath) + return 0; + } + else + return 0; + } + else if (!(ipath = strdup(imagepath))) + return 0; + + if (defdevice) { + defdev = strdup(defdevice); + device_kind = prom_get_devtype(defdev); + } else if (device_kind == -1) + device_kind = prom_get_devtype(ipath); + + /* + * When an iscsi iqn is present, it may have embedded colons, so + * don't parse off anything. + */ + if (device_kind != FILE_DEVICE_NET && + device_kind != FILE_DEVICE_ISCSI && + strchr(defdev, ':') != NULL) { + if ((ptr = strrchr(defdev, ':')) != NULL) + *ptr = 0; /* remove trailing : from defdevice if necessary */ + } + + /* This will not properly handle an obp-tftp argument list + * with elements after the filename; that is handled below. + */ + if (device_kind != FILE_DEVICE_NET && + device_kind != FILE_DEVICE_ISCSI && + strchr(ipath, ':') != NULL) { + if ((ptr = strrchr(ipath, ',')) != NULL) { + char *colon = strrchr(ipath, ':'); + /* If a ':' occurs *after* a ',', then we assume that there is + no filename */ + if (!colon || colon < ptr) { + result->file = strdup(ptr+1); + /* Trim the filename off */ + *ptr = 0; + } + } + } + + if (device_kind == FILE_DEVICE_NET) { + if (strchr(ipath, ':')) { + if (extract_netboot_args(ipath, result) == 0) + return 0; + } else { + /* If we didn't get a ':' then look only in netinfo */ + extract_netinfo_args(result); + result->file = strdup(ipath); + } + + if (!defdev) + result->dev = netdev_path_to_dev(ipath); + } else if (device_kind != FILE_DEVICE_ISCSI && + (ptr = strrchr(ipath, ':')) != NULL) { + *ptr = 0; + result->dev = strdup(ipath); + if (*(ptr+1)) + result->part = simple_strtol(ptr+1, NULL, 10); + } else if (!defdev) { + result->dev = strdup(ipath); + } else if (strlen(ipath)) { + result->file = strdup(ipath); + } else { + free(defdev); + return 0; + } + + if (!result->dev && defdev) + result->dev = strdup(defdev); + + if (result->part < 0) + result->part = defpart; + + if (!result->file) + result->file = strdup(deffile); + + free(ipath); + if (defdev) + free(defdev); + return 1; } + static int file_block_open( struct boot_file_t* file, - const char* dev_name, - const char* file_name, + struct boot_fspec_t* fspec, int partition) { - struct partition_t* parts; - struct partition_t* p; - struct partition_t* found; - - parts = partitions_lookup(dev_name); - found = NULL; - + struct partition_t* parts; + struct partition_t* p; + struct partition_t* found; + + parts = partitions_lookup(fspec->dev); + found = NULL; + #if DEBUG - if (parts) - prom_printf("partitions:\n"); - else - prom_printf("no partitions found.\n"); + if (parts) + prom_printf("partitions:\n"); + else + prom_printf("no partitions found.\n"); #endif - for (p = parts; p && !found; p=p->next) { + for (p = parts; p && !found; p=p->next) { + DEBUG_F("number: %02d, start: 0x%08lx, length: 0x%08lx\n", + p->part_number, p->part_start, p->part_size ); + if (partition == -1) { + file->fs = fs_open( file, p, fspec ); + if (file->fs == NULL || fserrorno != FILE_ERR_OK) + continue; + else { + partition = p->part_number; + goto done; + } + } + if ((partition >= 0) && (partition == p->part_number)) + found = p; #if DEBUG - prom_printf("number: %02d, start: 0x%08lx, length: 0x%08lx\n", - p->part_number, p->part_start, p->part_size ); + if (found) + prom_printf(" (match)\n"); #endif - if (partition == -1) { - file->fs = fs_open( file, dev_name, p, file_name ); - if (file->fs != NULL) - goto bail; - } - if ((partition >= 0) && (partition == p->part_number)) - found = p; -#if DEBUG - if (found) - prom_printf(" (match)\n"); -#endif - } - - /* Note: we don't skip when found is NULL since we can, in some - * cases, let OF figure out a default partition. - */ - DEBUG_F( "Using OF defaults.. (found = 0x%x)\n", found ); - file->fs = fs_open( file, dev_name, found, file_name ); - -bail: - if (parts) - partitions_free(parts); - - return file->fs ? FILE_ERR_OK : FILE_ERR_NOTFOUND; + } + + /* Note: we don't skip when found is NULL since we can, in some + * cases, let OF figure out a default partition. + */ + DEBUG_F( "Using OF defaults.. (found = %p)\n", found ); + file->fs = fs_open( file, found, fspec ); + +done: + if (parts) + partitions_free(parts); + + return fserrorno; } static int -file_net_open( struct boot_file_t* file, - const char* dev_name, - const char* file_name) +file_net_open(struct boot_file_t* file, struct boot_fspec_t *fspec) { - file->fs = fs_of_netboot; - return fs_of_netboot->open(file, dev_name, NULL, file_name); + file->fs = fs_of_netboot; + return fs_of_netboot->open(file, NULL, fspec); } static int @@ -154,106 +626,68 @@ default_read( struct boot_file_t* file, unsigned int size, void* buffer) { - prom_printf("WARNING ! default_read called !\n"); - return FILE_ERR_EOF; + prom_printf("WARNING ! default_read called !\n"); + return FILE_ERR_EOF; } static int default_seek( struct boot_file_t* file, unsigned int newpos) { - prom_printf("WARNING ! default_seek called !\n"); - return FILE_ERR_EOF; + prom_printf("WARNING ! default_seek called !\n"); + return FILE_ERR_EOF; } static int default_close( struct boot_file_t* file) { - prom_printf("WARNING ! default_close called !\n"); - return FILE_ERR_OK; + prom_printf("WARNING ! default_close called !\n"); + return FILE_ERR_OK; } static struct fs_t fs_default = { - "defaults", - NULL, - default_read, - default_seek, - default_close + "defaults", + NULL, + default_read, + default_seek, + default_close }; -int open_file( const struct boot_fspec_t* spec, - struct boot_file_t* file) +int open_file(struct boot_fspec_t* spec, struct boot_file_t* file) { - static char temp[1024]; - static char temps[64]; - char *dev_name; - char *file_name = NULL; - phandle dev; - int result; - int partition; - - memset(file, 0, sizeof(struct boot_file_t*)); - file->fs = &fs_default; - - /* Lookup the OF device path */ - /* First, see if a device was specified for the kernel - * if not, we hope that the user wants a kernel on the same - * drive and partition as yaboot itself */ - if (!spec->dev) - strcpy(spec->dev, bootdevice); - strncpy(temp,spec->dev,1024); - dev_name = parse_device_path(temp, &file_name, &partition); - if (file_name == NULL) - file_name = (char *)spec->file; - if (file_name == NULL) { - prom_printf("booting without a file name not yet supported !\n"); - return FILE_ERR_NOTFOUND; - } - if (partition == -1) - partition = spec->part; + int result; -#if DEBUG - prom_printf("dev_path = %s\nfile_name = %s\npartition = %d\n", - dev_name, file_name, partition); -#endif - /* Find OF device phandle */ - dev = prom_finddevice(dev_name); - if (dev == PROM_INVALID_HANDLE) { - prom_printf("device not found !\n"); - return FILE_ERR_NOTFOUND; - } -#if DEBUG - prom_printf("dev_phandle = %08lx\n", dev); -#endif - /* Check the kind of device */ - result = prom_getprop(dev, "device_type", temps, 63); - if (result == -1) { - prom_printf("can't get for device\n"); - return FILE_ERR_NOTFOUND; - } - temps[result] = 0; - if (!strcmp(temps, "block")) - file->device_kind = FILE_DEVICE_BLOCK; - else if (!strcmp(temps, "network")) - file->device_kind = FILE_DEVICE_NET; - else { - prom_printf("Unkown device type <%s>\n", temps); - return FILE_ERR_NOTFOUND; - } - - switch(file->device_kind) { - case FILE_DEVICE_BLOCK: -#if DEBUG - prom_printf("device is a block device\n"); -#endif - return file_block_open(file, dev_name, file_name, partition); - case FILE_DEVICE_NET: -#if DEBUG - prom_printf("device is a network device\n"); -#endif - return file_net_open(file, dev_name, file_name); - } - return 0; + memset(file, 0, sizeof(struct boot_file_t*)); + file->fs = &fs_default; + + DEBUG_F("dev_path = %s\nfile_name = %s\npartition = %d\n", + spec->dev, spec->file, spec->part); + + result = prom_get_devtype(spec->dev); + if (result > 0) + file->device_kind = result; + else + return result; + + switch(file->device_kind) { + case FILE_DEVICE_BLOCK: + DEBUG_F("device is a block device\n"); + return file_block_open(file, spec, spec->part); + case FILE_DEVICE_ISCSI: + DEBUG_F("device is a iSCSI device\n"); + return file_block_open(file, spec, spec->part); + case FILE_DEVICE_NET: + DEBUG_F("device is a network device\n"); + return file_net_open(file, spec); + } + return 0; } + +/* + * Local variables: + * c-file-style: "k&r" + * c-basic-offset: 5 + * End: + */