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