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, const char* dev_name,
44 struct partition_t* part, const char* file_name);
45 static int of_read(struct boot_file_t* file, unsigned int size, void* buffer);
46 static int of_seek(struct boot_file_t* file, unsigned int newpos);
47 static int of_close(struct boot_file_t* file);
50 static int of_net_open(struct boot_file_t* file, const char* dev_name,
51 struct partition_t* part, const char* file_name);
52 static int of_net_read(struct boot_file_t* file, unsigned int size, void* buffer);
53 static int of_net_seek(struct boot_file_t* file, unsigned int newpos);
56 struct fs_t of_filesystem =
65 struct fs_t of_net_filesystem =
75 of_open(struct boot_file_t* file, const char* dev_name,
76 struct partition_t* part, const char* file_name)
78 static char buffer[1024];
85 strncpy(buffer, dev_name, 768);
89 sprintf(pn, "%02d", part->part_number);
92 if (file_name && strlen(file_name)) {
95 filename = strdup(file_name);
96 for (p = filename; *p; p++)
99 strcat(buffer, filename);
103 DEBUG_F("opening: \"%s\"\n", buffer);
105 file->of_device = prom_open(buffer);
107 DEBUG_F("file->of_device = %p\n", file->of_device);
111 if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0))
113 DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
114 return FILE_ERR_BAD_FSYS;
117 DEBUG_LEAVE(FILE_ERR_OK);
122 of_net_open(struct boot_file_t* file, const char* dev_name,
123 struct partition_t* part, const char* file_name)
125 static char buffer[1024];
132 strncpy(buffer, dev_name, 768);
133 if (file_name && strlen(file_name)) {
135 filename = strdup(file_name);
136 for (p = filename; *p; p++)
139 strcat(buffer, filename);
143 DEBUG_F("Opening: \"%s\"\n", buffer);
145 file->of_device = prom_open(buffer);
147 DEBUG_F("file->of_device = %p\n", file->of_device);
150 if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0))
152 DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
153 return FILE_ERR_BAD_FSYS;
156 file->buffer = prom_claim((void *)LOAD_BUFFER_POS, LOAD_BUFFER_SIZE, 0);
157 if (file->buffer == (void *)-1) {
158 prom_printf("Can't claim memory for TFTP download\n");
159 prom_close(file->of_device);
160 DEBUG_LEAVE(FILE_IOERR);
163 memset(file->buffer, 0, LOAD_BUFFER_SIZE);
167 file->len = prom_loadmethod(file->of_device, file->buffer);
169 DEBUG_F("result: %Ld\n", file->len);
171 DEBUG_LEAVE(FILE_ERR_OK);
176 of_read(struct boot_file_t* file, unsigned int size, void* buffer)
180 count = prom_read(file->of_device, buffer, size);
186 of_net_read(struct boot_file_t* file, unsigned int size, void* buffer)
188 unsigned int count, av;
190 av = file->len - file->pos;
191 count = size > av ? av : size;
192 memcpy(buffer, file->buffer + file->pos, count);
198 of_seek(struct boot_file_t* file, unsigned int newpos)
200 if (prom_seek(file->of_device, newpos)) {
205 return FILE_CANT_SEEK;
209 of_net_seek(struct boot_file_t* file, unsigned int newpos)
211 file->pos = (newpos > file->len) ? file->len : newpos;
216 of_close(struct boot_file_t* file)
220 DEBUG_F("<@%p>\n", file->of_device);
223 prom_release(file->buffer, LOAD_BUFFER_SIZE);
225 prom_close(file->of_device);
226 DEBUG_F("of_close called\n");
234 * c-file-style: "K&R"