X-Git-Url: http://git.ozlabs.org/?p=yaboot.git;a=blobdiff_plain;f=second%2Ffs_of.c;h=76474ee29744dc85158efee7b14bfb6fb63f9628;hp=abb006b0a7394d83a0a02eaa78962eadf5174f7e;hb=5d4289bddaef010cc14bcbeecfd13d5068b50a8e;hpb=f4ebbd9f7ea23e3f0fcbe098754580c220894628 diff --git a/second/fs_of.c b/second/fs_of.c index abb006b..76474ee 100644 --- a/second/fs_of.c +++ b/second/fs_of.c @@ -1,30 +1,35 @@ -/* OpenFirmware-based filesystem - - 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. - - BrokenFirmware cannot "read" from the network. We use tftp "load" method - for network boot for now, we may provide our own NFS implementation in - a later version. That means that we allocate a huge block of memory for - the entire file before loading it. We use the location where the kernel puts - RTAS, it's not used by the bootloader and if freed when the kernel is booted. - This will have to be changed if we plan to instanciate RTAS in the bootloader - itself - -*/ +/* + * fs_of.c - an implementation for OpenFirmware supported filesystems + * + * Copyright (C) 2001, 2002 Ethan Benson + * + * 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. + */ + +/* + * BrokenFirmware cannot "read" from the network. We use tftp "load" + * method for network boot for now, we may provide our own NFS + * implementation in a later version. That means that we allocate a + * huge block of memory for the entire file before loading it. We use + * the location where the kernel puts RTAS, it's not used by the + * bootloader and if freed when the kernel is booted. This will have + * to be changed if we plan to instanciate RTAS in the bootloader + * itself + */ #include "ctype.h" #include "types.h" @@ -34,208 +39,212 @@ #include "prom.h" #include "string.h" #include "partition.h" +#include "fdisk-part.h" #include "fs.h" - +#include "errors.h" +#include "debug.h" #define LOAD_BUFFER_POS 0x600000 -#define LOAD_BUFFER_SIZE 0x400000 - -static int of_open( struct boot_file_t* file, - const char* dev_name, - struct partition_t* part, - const char* file_name); -static int of_read( struct boot_file_t* file, - unsigned int size, - void* buffer); -static int of_seek( struct boot_file_t* file, - unsigned int newpos); -static int of_close( struct boot_file_t* file); - - -static int of_net_open( struct boot_file_t* file, - const char* dev_name, - struct partition_t* part, - const char* file_name); -static int of_net_read( struct boot_file_t* file, - unsigned int size, - void* buffer); -static int of_net_seek( struct boot_file_t* file, - unsigned int newpos); +/* this cannot be safely increased any further */ +#define LOAD_BUFFER_SIZE 0x600000 + +static int of_open(struct boot_file_t* file, const char* dev_name, + struct partition_t* part, const char* file_name); +static int of_read(struct boot_file_t* file, unsigned int size, void* buffer); +static int of_seek(struct boot_file_t* file, unsigned int newpos); +static int of_close(struct boot_file_t* file); + + +static int of_net_open(struct boot_file_t* file, const char* dev_name, + struct partition_t* part, const char* file_name); +static int of_net_read(struct boot_file_t* file, unsigned int size, void* buffer); +static int of_net_seek(struct boot_file_t* file, unsigned int newpos); struct fs_t of_filesystem = { - "built-in", - of_open, - of_read, - of_seek, - of_close + "built-in", + of_open, + of_read, + of_seek, + of_close }; struct fs_t of_net_filesystem = { - "built-in network", - of_net_open, - of_net_read, - of_net_seek, - of_close + "built-in network", + of_net_open, + of_net_read, + of_net_seek, + of_close }; - - static int -of_open( struct boot_file_t* file, - const char* dev_name, - struct partition_t* part, - const char* file_name) +of_open(struct boot_file_t* file, const char* dev_name, + struct partition_t* part, const char* file_name) { - static char buffer[1024]; - - DEBUG_ENTER; - DEBUG_OPEN; - - strncpy(buffer, dev_name, 1000); - strcat(buffer, ":"); - if (part) { - char pn[3]; - sprintf(pn, "%02d", part->part_number); - strcat(buffer, pn); - } - if (file_name && strlen(file_name)) { - if (part) - strcat(buffer, ","); - strcat(buffer, file_name); - } - - DEBUG_F("<%s>\n", buffer); - - file->of_device = prom_open(buffer); - - DEBUG_F("file->of_device = %08lx\n", file->of_device); - - file->pos = 0; - file->buffer = NULL; - if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0)) - { - DEBUG_LEAVE(FILE_ERR_NOTFOUND); - return FILE_ERR_NOTFOUND; - } - - DEBUG_LEAVE(FILE_ERR_OK); - return FILE_ERR_OK; + static char buffer[1024]; + char *filename; + char *p; + + DEBUG_ENTER; + DEBUG_OPEN; + + strncpy(buffer, dev_name, 768); + strcat(buffer, ":"); + if (part) { + if (part->sys_ind == LINUX_RAID) { + DEBUG_F("skipping because partition is marked LINUX_RAID\n"); + DEBUG_LEAVE(FILE_ERR_BAD_FSYS); + return FILE_ERR_BAD_FSYS; + } + char pn[3]; + sprintf(pn, "%02d", part->part_number); + strcat(buffer, pn); + } + if (file_name && strlen(file_name)) { + if (part) + strcat(buffer, ","); + filename = strdup(file_name); + for (p = filename; *p; p++) + if (*p == '/') + *p = '\\'; + strcat(buffer, filename); + free(filename); + } + + DEBUG_F("opening: \"%s\"\n", buffer); + + file->of_device = prom_open(buffer); + + DEBUG_F("file->of_device = %p\n", file->of_device); + + file->pos = 0; + file->buffer = NULL; + if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0)) + { + DEBUG_LEAVE(FILE_ERR_BAD_FSYS); + return FILE_ERR_BAD_FSYS; + } + + DEBUG_LEAVE(FILE_ERR_OK); + return FILE_ERR_OK; } static int -of_net_open( struct boot_file_t* file, - const char* dev_name, - struct partition_t* part, - const char* file_name) +of_net_open(struct boot_file_t* file, const char* dev_name, + struct partition_t* part, const char* file_name) { - static char buffer[1024]; - - DEBUG_ENTER; - DEBUG_OPEN; - - strncpy(buffer, dev_name, 1000); - strcat(buffer, ":0"); - if (file_name && strlen(file_name)) { - strcat(buffer, ","); - strcat(buffer, file_name); - } - - DEBUG_F("<%s>\n", buffer); - - file->of_device = prom_open(buffer); - - DEBUG_F("file->of_device = %08lx\n", file->of_device); - - file->pos = 0; - if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0)) - { - DEBUG_LEAVE(FILE_ERR_NOTFOUND); - return FILE_ERR_NOTFOUND; - } - - file->buffer = prom_claim((void *)LOAD_BUFFER_POS, LOAD_BUFFER_SIZE, 0); - if (file->buffer == (void *)-1) { - prom_printf("Can't claim memory for TFTP download\n"); - prom_close(file->of_device); - DEBUG_LEAVE(FILE_ERR_NOTFOUND); - return FILE_ERR_NOTFOUND; - } - memset(file->buffer, 0, LOAD_BUFFER_SIZE); - - DEBUG_F("TFP...\n"); - - file->len = prom_loadmethod(file->of_device, file->buffer); - - DEBUG_F("result: %d\n", file->len); - - - DEBUG_LEAVE(FILE_ERR_OK); - return FILE_ERR_OK; + static char buffer[1024]; + char *filename; + char *p; + + DEBUG_ENTER; + DEBUG_OPEN; + + strncpy(buffer, dev_name, 768); + if (file_name && strlen(file_name)) { + strcat(buffer, ","); + filename = strdup(file_name); + for (p = filename; *p; p++) + if (*p == '/') + *p = '\\'; + strcat(buffer, filename); + free(filename); + } + + DEBUG_F("Opening: \"%s\"\n", buffer); + + file->of_device = prom_open(buffer); + + DEBUG_F("file->of_device = %p\n", file->of_device); + + file->pos = 0; + if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0)) + { + DEBUG_LEAVE(FILE_ERR_BAD_FSYS); + return FILE_ERR_BAD_FSYS; + } + + file->buffer = prom_claim((void *)LOAD_BUFFER_POS, LOAD_BUFFER_SIZE, 0); + if (file->buffer == (void *)-1) { + prom_printf("Can't claim memory for TFTP download\n"); + prom_close(file->of_device); + DEBUG_LEAVE(FILE_IOERR); + return FILE_IOERR; + } + memset(file->buffer, 0, LOAD_BUFFER_SIZE); + + DEBUG_F("TFP...\n"); + + file->len = prom_loadmethod(file->of_device, file->buffer); + + DEBUG_F("result: %Ld\n", file->len); + + DEBUG_LEAVE(FILE_ERR_OK); + return FILE_ERR_OK; } static int -of_read( struct boot_file_t* file, - unsigned int size, - void* buffer) +of_read(struct boot_file_t* file, unsigned int size, void* buffer) { - unsigned int count; - - count = prom_read(file->of_device, buffer, size); - file->pos += count; - return count; + unsigned int count; + + count = prom_read(file->of_device, buffer, size); + file->pos += count; + return count; } static int -of_net_read( struct boot_file_t* file, - unsigned int size, - void* buffer) +of_net_read(struct boot_file_t* file, unsigned int size, void* buffer) { - unsigned int count, av; - - av = file->len - file->pos; - count = size > av ? av : size; - memcpy(buffer, file->buffer + file->pos, count); - file->pos += count; - return count; + unsigned int count, av; + + av = file->len - file->pos; + count = size > av ? av : size; + memcpy(buffer, file->buffer + file->pos, count); + file->pos += count; + return count; } static int -of_seek( struct boot_file_t* file, - unsigned int newpos) +of_seek(struct boot_file_t* file, unsigned int newpos) { - if (prom_seek(file->of_device, newpos)) { - file->pos = newpos; - return FILE_ERR_OK; - } - - return FILE_CANT_SEEK; + if (prom_seek(file->of_device, newpos)) { + file->pos = newpos; + return FILE_ERR_OK; + } + + return FILE_CANT_SEEK; } static int -of_net_seek( struct boot_file_t* file, - unsigned int newpos) +of_net_seek(struct boot_file_t* file, unsigned int newpos) { - file->pos = (newpos > file->len) ? file->len : newpos; - return FILE_ERR_OK; + file->pos = (newpos > file->len) ? file->len : newpos; + return FILE_ERR_OK; } static int -of_close( struct boot_file_t* file) +of_close(struct boot_file_t* file) { - DEBUG_ENTER; - DEBUG_F("<@0x%08lx>n", file->of_device); + DEBUG_ENTER; + DEBUG_F("<@%p>\n", file->of_device); - if (file->buffer) { - prom_release(file->buffer, LOAD_BUFFER_SIZE); - } - prom_close(file->of_device); + if (file->buffer) { + prom_release(file->buffer, LOAD_BUFFER_SIZE); + } + prom_close(file->of_device); + DEBUG_F("of_close called\n"); - DEBUG_LEAVE(0); - - return 0; + DEBUG_LEAVE(0); + return 0; } +/* + * Local variables: + * c-file-style: "k&r" + * c-basic-offset: 5 + * End: + */