1 /* OpenFirmware-based filesystem
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.
19 BrokenFirmware cannot "read" from the network. We use tftp "load" method
20 for network boot for now, we may provide our own NFS implementation in
21 a later version. That means that we allocate a huge block of memory for
22 the entire file before loading it. We use the location where the kernel puts
23 RTAS, it's not used by the bootloader and if freed when the kernel is booted.
24 This will have to be changed if we plan to instanciate RTAS in the bootloader
36 #include "partition.h"
40 #define LOAD_BUFFER_POS 0x600000
41 #define LOAD_BUFFER_SIZE 0x400000
43 static int of_open( struct boot_file_t* file,
45 struct partition_t* part,
46 const char* file_name);
47 static int of_read( struct boot_file_t* file,
50 static int of_seek( struct boot_file_t* file,
52 static int of_close( struct boot_file_t* file);
55 static int of_net_open( struct boot_file_t* file,
57 struct partition_t* part,
58 const char* file_name);
59 static int of_net_read( struct boot_file_t* file,
62 static int of_net_seek( struct boot_file_t* file,
66 struct fs_t of_filesystem =
75 struct fs_t of_net_filesystem =
87 of_open( struct boot_file_t* file,
89 struct partition_t* part,
90 const char* file_name)
92 static char buffer[1024];
97 strncpy(buffer, dev_name, 1000);
101 sprintf(pn, "%02d", part->part_number);
104 if (file_name && strlen(file_name)) {
107 strcat(buffer, file_name);
110 DEBUG_F("<%s>\n", buffer);
112 file->of_device = prom_open(buffer);
114 DEBUG_F("file->of_device = %08lx\n", file->of_device);
118 if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0))
120 DEBUG_LEAVE(FILE_ERR_NOTFOUND);
121 return FILE_ERR_NOTFOUND;
124 DEBUG_LEAVE(FILE_ERR_OK);
129 of_net_open( struct boot_file_t* file,
130 const char* dev_name,
131 struct partition_t* part,
132 const char* file_name)
134 static char buffer[1024];
139 strncpy(buffer, dev_name, 1000);
140 strcat(buffer, ":0");
141 if (file_name && strlen(file_name)) {
143 strcat(buffer, file_name);
146 DEBUG_F("<%s>\n", buffer);
148 file->of_device = prom_open(buffer);
150 DEBUG_F("file->of_device = %08lx\n", file->of_device);
153 if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0))
155 DEBUG_LEAVE(FILE_ERR_NOTFOUND);
156 return FILE_ERR_NOTFOUND;
159 file->buffer = prom_claim((void *)LOAD_BUFFER_POS, LOAD_BUFFER_SIZE, 0);
160 if (file->buffer == (void *)-1) {
161 prom_printf("Can't claim memory for TFTP download\n");
162 prom_close(file->of_device);
163 DEBUG_LEAVE(FILE_ERR_NOTFOUND);
164 return FILE_ERR_NOTFOUND;
166 memset(file->buffer, 0, LOAD_BUFFER_SIZE);
170 file->len = prom_loadmethod(file->of_device, file->buffer);
172 DEBUG_F("result: %d\n", file->len);
175 DEBUG_LEAVE(FILE_ERR_OK);
180 of_read( struct boot_file_t* file,
186 count = prom_read(file->of_device, buffer, size);
192 of_net_read( struct boot_file_t* file,
196 unsigned int count, av;
198 av = file->len - file->pos;
199 count = size > av ? av : size;
200 memcpy(buffer, file->buffer + file->pos, count);
206 of_seek( struct boot_file_t* file,
209 if (prom_seek(file->of_device, newpos)) {
214 return FILE_CANT_SEEK;
218 of_net_seek( struct boot_file_t* file,
221 file->pos = (newpos > file->len) ? file->len : newpos;
226 of_close( struct boot_file_t* file)
230 DEBUG_F("<@0x%08lx>n", file->of_device);
233 prom_release(file->buffer, LOAD_BUFFER_SIZE);
235 prom_close(file->of_device);