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