3 Copyright (C) 1999 Benjamin Herrenschmidt
7 Copyright (C) 1996 Maurizio Plaza
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 Note: This version is way too slow due to the way we use bmap. This
25 should be replaced by an iterator.
34 #include "partition.h"
38 #define MAX_READ_RANGE 256
42 #include "linux/ext2_fs.h"
43 #include "ext2fs/ext2fs.h"
45 static int ext2_open( struct boot_file_t* file,
47 struct partition_t* part,
48 const char* file_name);
49 static int ext2_read( struct boot_file_t* file,
52 static int ext2_seek( struct boot_file_t* file,
54 static int ext2_close( struct boot_file_t* file);
56 struct fs_t ext2_filesystem =
65 /* IO manager structure for the ext2 library */
67 static errcode_t linux_open (const char *name, int flags, io_channel * channel);
68 static errcode_t linux_close (io_channel channel);
69 static errcode_t linux_set_blksize (io_channel channel, int blksize);
70 static errcode_t linux_read_blk (io_channel channel, unsigned long block, int count, void *data);
71 static errcode_t linux_write_blk (io_channel channel, unsigned long block, int count, const void *data);
72 static errcode_t linux_flush (io_channel channel);
74 static struct struct_io_manager struct_linux_manager =
76 EXT2_ET_MAGIC_IO_MANAGER,
86 static io_manager linux_io_manager = &struct_linux_manager;
88 /* Currently, we have a mess between what is in the file structure
89 * and what is stored globally here. I'll clean this up later
91 static int opened = 0; /* We can't open twice ! */
92 static unsigned int bs; /* Blocksize */
93 static unsigned long long doff; /* Byte offset where partition starts */
94 static ino_t root,cwd;
95 static ext2_filsys fs = 0;
96 static struct boot_file_t* cur_file;
97 static char *block_buffer = NULL;
100 static unsigned long read_range_start;
101 static unsigned long read_range_count;
102 static unsigned long read_last_logical;
103 static unsigned long read_total;
104 static unsigned long read_max;
105 static struct boot_file_t* read_cur_file;
106 static errcode_t read_result;
107 static char* read_buffer;
109 static int read_dump_range(void);
110 static int read_iterator(ext2_filsys fs, blk_t *blocknr, int lg_block, void *private);
111 #else /* FAST_VERSION */
112 static struct ext2_inode cur_inode;
113 #endif /* FAST_VERSION */
115 void com_err (const char *a, long i, const char *fmt,...)
117 prom_printf ((char *) fmt);
121 ext2_open( struct boot_file_t* file,
122 const char* dev_name,
123 struct partition_t* part,
124 const char* file_name)
127 static char buffer[1024];
134 prom_printf("ext2_open() : fs busy\n");
135 return FILE_ERR_NOTFOUND;
137 if (file->device_kind != FILE_DEVICE_BLOCK) {
138 prom_printf("Can't open ext2 filesystem on non-block device\n");
139 return FILE_ERR_NOTFOUND;
144 /* We don't care too much about the device block size since we run
145 * thru the deblocker. We may have to change that is we plan to be
146 * compatible with older versions of OF
151 doff = (unsigned long long)(part->part_start) * part->blocksize;
155 DEBUG_F("partition offset: %d\n", doff);
157 /* Open the OF device for the entire disk */
158 strncpy(buffer, dev_name, 1020);
159 strcat(buffer, ":0");
161 DEBUG_F("<%s>\n", buffer);
163 file->of_device = prom_open(buffer);
165 DEBUG_F("file->of_device = %08lx\n", file->of_device);
167 if (file->of_device == PROM_INVALID_HANDLE) {
169 DEBUG_F("Can't open device %s\n", file->of_device);
171 return FILE_ERR_NOTFOUND;
175 /* Open the ext2 filesystem */
176 result = ext2fs_open (buffer, EXT2_FLAG_RW, 0, 0, linux_io_manager, &fs);
179 if(result == EXT2_ET_BAD_MAGIC)
181 DEBUG_F( "ext2fs_open returned bad magic loading file %s\n",
186 DEBUG_F( "ext2fs_open error #%d while loading file %s\n",
193 /* Allocate the block buffer */
194 block_buffer = malloc(fs->blocksize * 2);
197 DEBUG_F("ext2fs: can't alloc block buffer (%d bytes)\n", fs->blocksize * 2);
202 /* Lookup file by pathname */
203 root = cwd = EXT2_ROOT_INO;
204 result = ext2fs_namei_follow(fs, root, cwd, file_name, &file->inode);
207 DEBUG_F("ext2fs_namei error #%d while loading file %s\n", result, file_name);
212 result = ext2fs_follow_link(fs, root, cwd, file->inode, &file->inode);
215 DEBUG_F("ext2fs_follow_link error #%d while loading file %s\n", result, file_name);
222 result = ext2fs_read_inode(fs, file->inode, &cur_inode);
225 DEBUG_F("ext2fs_read_inode error #%d while loading file %s\n", result, file_name);
229 #endif /* FAST_VERSION */
239 prom_close(file->of_device);
245 DEBUG_LEAVE(FILE_ERR_NOTFOUND);
246 return FILE_ERR_NOTFOUND;
249 DEBUG_LEAVE(FILE_ERR_OK);
256 read_dump_range(void)
258 int count = read_range_count;
262 DEBUG_F(" dumping range: start: 0x%x count: 0x%x\n",
263 read_range_count, read_range_start);
265 /* Check if we need to handle a special case for the last block */
266 if ((count * bs) > read_max)
270 read_result = io_channel_read_blk(fs->io, read_range_start, count, read_buffer);
276 read_cur_file->pos += size;
277 read_range_count -= count;
278 read_range_start += count;
279 read_last_logical += count;
281 /* Handle remaining block */
282 if (read_max && read_range_count) {
283 read_result = io_channel_read_blk(fs->io, read_range_start, 1, block_buffer);
286 memcpy(read_buffer, block_buffer, read_max);
287 read_cur_file->pos += read_max;
288 read_total += read_max;
291 read_range_count = read_range_start = 0;
293 return (read_max == 0) ? BLOCK_ABORT : 0;
297 read_iterator(ext2_filsys fs, blk_t *blocknr, int lg_block, void *private)
300 DEBUG_F("read_it: p_bloc: 0x%x, l_bloc: 0x%x, f_pos: 0x%x, rng_pos: 0x%x ",
301 *blocknr, lg_block, read_cur_file->pos, read_last_logical);
305 DEBUG_F(" <skip lg>\n");
310 /* If we have not reached the start block yet, we skip */
311 if (lg_block < read_cur_file->pos / bs) {
313 DEBUG_F(" <skip pos>\n");
318 /* If block is contiguous to current range, just extend range,
319 * exit if we pass the remaining bytes count to read
321 if (read_range_start && read_range_count < MAX_READ_RANGE
322 && (*blocknr == read_range_start + read_range_count)
323 && (lg_block == read_last_logical + read_range_count)) {
325 DEBUG_F(" block in range\n");
328 return ((read_range_count * bs) >= read_max) ? BLOCK_ABORT : 0;
331 /* Range doesn't match. Dump existing range */
332 if (read_range_start) {
334 DEBUG_F(" calling dump range \n");
336 if (read_dump_range())
340 /* Here we handle holes in the file */
341 if (lg_block && lg_block != read_last_logical) {
344 DEBUG_F(" hole from lg_bloc 0x%x\n", read_last_logical);
346 if (read_cur_file->pos % bs) {
347 int offset = read_cur_file->pos % bs;
348 int size = bs - offset;
351 memset(read_buffer, 0, size);
355 read_cur_file->pos += size;
360 nzero = (lg_block - read_last_logical) * bs;
362 if (nzero > read_max)
364 memset(read_buffer, 0, nzero);
367 read_buffer += nzero;
368 read_cur_file->pos += nzero;
372 read_last_logical = lg_block;
375 /* If we are not aligned, handle that case */
376 if (read_cur_file->pos % bs) {
377 int offset = read_cur_file->pos % bs;
378 int size = bs - offset;
380 DEBUG_F(" handle unaligned start\n");
382 read_result = io_channel_read_blk(fs->io, *blocknr, 1, block_buffer);
387 memcpy(read_buffer, block_buffer + offset, size);
388 read_cur_file->pos += size;
392 read_last_logical = lg_block + 1;
393 return (read_max == 0) ? BLOCK_ABORT : 0;
396 /* If there is still a physical block to add, then create a new range */
399 DEBUG_F(" new range\n");
401 read_range_start = *blocknr;
402 read_range_count = 1;
403 return (bs >= read_max) ? BLOCK_ABORT : 0;
412 #endif /* FAST_VERSION */
415 ext2_read( struct boot_file_t* file,
423 return FILE_ERR_NOTFOUND;
426 DEBUG_F("ext_read() from pos 0x%x, size: 0x%x\n", file->pos, size);
429 read_cur_file = file;
430 read_range_start = 0;
431 read_range_count = 0;
432 read_last_logical = file->pos / bs;
435 read_buffer = (unsigned char*)buffer;
438 retval = ext2fs_block_iterate(fs, file->inode, 0, 0, read_iterator, 0);
439 if (retval == BLOCK_ABORT)
440 retval = read_result;
441 if (!retval && read_range_start) {
443 DEBUG_F("on exit: range_start is 0x%x, calling dump...\n",
447 retval = read_result;
450 prom_printf ("ext2: i/o error %d in read\n", retval);
454 #else /* FAST_VERSION */
456 unsigned int read = 0;
459 return FILE_ERR_NOTFOUND;
462 DEBUG_F("ext_read() from pos 0x%x, size: 0x%x\n", file->pos, size);
466 blk_t fblock = file->pos / bs;
468 unsigned int blkorig, s, b;
471 status = ext2fs_bmap(fs, file->inode, &cur_inode,
472 block_buffer, 0, fblock, &pblock);
475 DEBUG_F("ext2fs_bmap(fblock:%d) return: %d\n", fblock, status);
478 blkorig = fblock * bs;
479 b = file->pos - blkorig;
480 s = ((bs - b) > size) ? size : (bs - b);
482 unsigned long long pos =
483 ((unsigned long long)pblock) * (unsigned long long)bs;
485 prom_lseek(file->of_device, pos);
486 status = prom_read(file->of_device, block_buffer, bs);
488 prom_printf("ext2: io error in read, ex: %d, got: %d\n",
493 memset(block_buffer, 0, bs);
495 memcpy(buffer, block_buffer + b, s);
502 #endif /* FAST_VERSION */
506 ext2_seek( struct boot_file_t* file,
510 return FILE_ERR_NOTFOUND;
517 ext2_close( struct boot_file_t* file)
520 return FILE_ERR_NOTFOUND;
530 prom_close(file->of_device);
537 static errcode_t linux_open (const char *name, int flags, io_channel * channel)
543 return EXT2_ET_BAD_DEVICE_NAME;
544 io = (io_channel) malloc (sizeof (struct struct_io_channel));
546 return EXT2_ET_BAD_DEVICE_NAME;
547 memset (io, 0, sizeof (struct struct_io_channel));
548 io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
549 io->manager = linux_io_manager;
550 io->name = (char *) malloc (strlen (name) + 1);
551 strcpy (io->name, name);
560 static errcode_t linux_close (io_channel channel)
566 static errcode_t linux_set_blksize (io_channel channel, int blksize)
568 channel->block_size = bs = blksize;
571 block_buffer = malloc(bs * 2);
576 static errcode_t linux_read_blk (io_channel channel, unsigned long block, int count, void *data)
579 unsigned long long tempb;
584 tempb = (((unsigned long long) block) *
585 ((unsigned long long)bs)) + (unsigned long long)doff;
586 size = (count < 0) ? -count : count * bs;
587 prom_lseek(cur_file->of_device, tempb);
588 if (prom_read(cur_file->of_device, data, size) != size) {
589 prom_printf ("\nRead error on block %d", block);
590 return EXT2_ET_SHORT_READ;
595 static errcode_t linux_write_blk (io_channel channel, unsigned long block, int count, const void *data)
600 static errcode_t linux_flush (io_channel channel)