1 /* $NetBSD: ustarfs.c,v 1.7 2008/04/28 20:23:19 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <lib/libsa/stand.h> 33 #include <lib/libkern/libkern.h> 34 35 #include <machine/param.h> 36 #include <machine/sbd.h> 37 #include <machine/sector.h> 38 39 #include "local.h" 40 #include "common.h" 41 42 bool __ustarfs_file(int, char *, size_t *); 43 bool __block_read(uint8_t *, int); 44 bool __block_read_n(uint8_t *, int, int); 45 void __change_volume(int); 46 47 enum { USTAR_BLOCK_SIZE = 8192 };/* Check src/distrib/common/buildfloppies.sh */ 48 struct volume { 49 int max_block; 50 int current_volume; 51 int block_offset; 52 } __volume; 53 54 bool 55 ustarfs_load(const char *file, void **addrp, size_t *sizep) 56 { 57 char fname[16]; 58 int block = 16; 59 size_t sz; 60 int maxblk; 61 62 if (DEVICE_CAPABILITY.active_device == NVSRAM_BOOTDEV_HARDDISK) 63 maxblk = 0x1fffffff; /* no limit */ 64 else if (DEVICE_CAPABILITY.active_device == NVSRAM_BOOTDEV_FLOPPYDISK) 65 /* 66 * Although phisical format isn't 2D, volume size is 67 * limited to size of 2D. 68 */ 69 maxblk = (77 + 76) * 13; 70 else { 71 printf("not supported device.\n"); 72 return false; 73 } 74 75 /* Truncate to ustar block boundary */ 76 __volume.max_block = (maxblk / (USTAR_BLOCK_SIZE >> DEV_BSHIFT)) * 77 (USTAR_BLOCK_SIZE >> DEV_BSHIFT); 78 __volume.block_offset = 0; 79 __volume.current_volume = 0; 80 81 /* Find file */ 82 while (/*CONSTCOND*/1) { 83 if (!__ustarfs_file(block, fname, &sz)) 84 return false; 85 86 if (strcmp(file, fname) == 0) 87 break; 88 block += (ROUND_SECTOR(sz) >> DEV_BSHIFT) + 1; 89 } 90 block++; /* skip tar header */ 91 *sizep = sz; 92 93 /* Load file */ 94 sz = ROUND_SECTOR(sz); 95 if ((*addrp = alloc(sz)) == 0) { 96 printf("%s: can't allocate memory.\n", __func__); 97 return false; 98 } 99 100 if (!__block_read_n(*addrp, block, sz >> DEV_BSHIFT)) { 101 printf("%s: can't load file.\n", __func__); 102 dealloc(*addrp, sz); 103 return false; 104 } 105 106 return true; 107 } 108 109 bool 110 __ustarfs_file(int start_block, char *file, size_t *size) 111 { 112 uint8_t buf[512]; 113 114 if (!__block_read(buf, start_block)) { 115 printf("can't read tar header.\n"); 116 return false; 117 } 118 if (((*(uint32_t *)(buf + 256)) & 0xffffff) != 0x757374) { 119 printf("bad tar magic.\n"); 120 return false; 121 } 122 *size = strtoul((char *)buf + 124, 0, 0); 123 strncpy(file, (char *)buf, 16); 124 125 return true; 126 } 127 128 bool 129 __block_read_n(uint8_t *buf, int blk, int count) 130 { 131 int i; 132 133 for (i = 0; i < count; i++, buf += DEV_BSIZE) 134 if (!__block_read(buf, blk + i)) 135 return false; 136 137 return true; 138 } 139 140 bool 141 __block_read(uint8_t *buf, int blk) 142 { 143 int vol; 144 145 if ((vol = blk / __volume.max_block) != __volume.current_volume) { 146 __change_volume(vol); 147 __volume.current_volume = vol; 148 /* volume offset + ustarfs header (8k) */ 149 __volume.block_offset = vol * __volume.max_block - 16; 150 } 151 152 return sector_read(0, buf, blk - __volume.block_offset); 153 } 154 155 void 156 __change_volume(int volume) 157 { 158 uint8_t buf[512]; 159 int i; 160 161 while (/*CONSTCOND*/1) { 162 printf("insert disk %d, and press return...", volume + 1); 163 while (getchar() != '\r') 164 ; 165 printf("\n"); 166 if (!sector_read(0, buf, 0)) 167 continue; 168 if (*(uint32_t *)buf != 0x55535441) { /* "USTAR" */ 169 printf("invalid magic.\n"); 170 continue; 171 } 172 if ((i = buf[8] - '0') != volume + 1) { 173 printf("invalid volume number. disk=%d requested=%d\n", 174 i, volume + 1); 175 continue; 176 } 177 return; 178 } 179 } 180