1 /* $NetBSD: mboot.c,v 1.9 2011/10/01 15:59:01 chs Exp $ */ 2 3 /*- 4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Minoura Makoto. 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 <sys/types.h> 33 #include <machine/disklabel.h> 34 35 int bootmain(int); 36 37 struct iocs_readcap { 38 unsigned long block; 39 unsigned long size; 40 }; 41 static inline int 42 IOCS_BITSNS (int row) 43 { 44 register unsigned int reg_d0 __asm ("%d0"); 45 46 __asm volatile ("movel %1,%%d1\n\t" 47 "movel #0x04,%0\n\t" 48 "trap #15" 49 : "=d" (reg_d0) 50 : "ri" ((int) row) 51 : "%d1"); 52 53 return reg_d0; 54 } 55 static inline void 56 IOCS_B_PRINT (const char *str) 57 { 58 __asm volatile ("moval %0,%%a1\n\t" 59 "movel #0x21,%%d0\n\t" 60 "trap #15\n\t" 61 : 62 : "a" ((int) str) 63 : "%a1", "%d0"); 64 return; 65 } 66 static inline int 67 IOCS_S_READCAP (int id, struct iocs_readcap *cap) 68 { 69 register int reg_d0 __asm ("%d0"); 70 71 __asm volatile ("moveml %%d4,%%sp@-\n\t" 72 "movel %2,%%d4\n\t" 73 "moval %3,%%a1\n\t" 74 "movel #0x25,%%d1\n\t" 75 "movel #0xf5,%%d0\n\t" 76 "trap #15\n\t" 77 "moveml %%sp@+,%%d4" 78 : "=d" (reg_d0), "=m" (*cap) 79 : "ri" (id), "g" ((int) cap) 80 : "%d1", "%a1"); 81 82 return reg_d0; 83 } 84 static inline int 85 IOCS_S_READ (int pos, int blk, int id, int size, void *buf) 86 { 87 register int reg_d0 __asm ("%d0"); 88 89 __asm volatile ("moveml %%d3-%%d5,%%sp@-\n\t" 90 "movel %2,%%d2\n\t" 91 "movel %3,%%d3\n\t" 92 "movel %4,%%d4\n\t" 93 "movel %5,%%d5\n\t" 94 "moval %6,%%a1\n\t" 95 "movel #0x26,%%d1\n\t" 96 "movel #0xf5,%%d0\n\t" 97 "trap #15\n\t" 98 "moveml %%sp@+,%%d3-%%d5" 99 : "=d" (reg_d0), "=m" (*(char*) buf) 100 : "ri" (pos), "ri" (blk), "ri" (id), "ri" (size), "g" ((int) buf) 101 : "%d1", "%d2", "%a1"); 102 103 return reg_d0; 104 } 105 106 static inline int 107 IOCS_S_READEXT (int pos, int blk, int id, int size, void *buf) 108 { 109 register int reg_d0 __asm ("%d0"); 110 111 __asm volatile ("moveml %%d3-%%d5,%%sp@-\n\t" 112 "movel %2,%%d2\n\t" 113 "movel %3,%%d3\n\t" 114 "movel %4,%%d4\n\t" 115 "movel %5,%%d5\n\t" 116 "moval %6,%%a1\n\t" 117 "movel #0x26,%%d1\n\t" 118 "movel #0xf5,%%d0\n\t" 119 "trap #15\n\t" 120 "moveml %%sp@+,%%d3-%%d5" 121 : "=d" (reg_d0), "=m" (*(char*) buf) 122 : "ri" (pos), "ri" (blk), "ri" (id), "ri" (size), "g" ((int) buf) 123 : "%d1", "%d2", "%a1"); 124 125 return reg_d0; 126 } 127 128 #define PART_BOOTABLE 0 129 #define PART_UNUSED 1 130 #define PART_INUSE 2 131 132 133 134 int 135 bootmain(int scsiid) 136 { 137 struct iocs_readcap cap; 138 int size; 139 140 if (IOCS_BITSNS(0) & 1) /* ESC key */ 141 return 0; 142 143 if (IOCS_S_READCAP(scsiid, &cap) < 0) { 144 IOCS_B_PRINT("Error in reading.\r\n"); 145 return 0; 146 } 147 size = cap.size >> 9; 148 149 { 150 long *label = (void*) 0x3000; 151 if (IOCS_S_READ(0, 1, scsiid, size, label) < 0) { 152 IOCS_B_PRINT("Error in reading.\r\n"); 153 return 0; 154 } 155 if (label[0] != 0x58363853 || 156 label[1] != 0x43534931) { 157 IOCS_B_PRINT("Invalid disk.\r\n"); 158 return 0; 159 } 160 } 161 162 { 163 struct cpu_disklabel *label = (void*) 0x3000; 164 int i, firstinuse=-1; 165 unsigned char *t; 166 167 if (IOCS_S_READ(2<<(2-size), size?2:1, scsiid, size, label) < 0) { 168 IOCS_B_PRINT("Error in reading.\r\n"); 169 return 0; 170 } 171 t = label->dosparts[0].dp_typname; 172 if (t[0] != 'X' || t[1] != '6' || t[2] != '8' || t[3] != 'K') { 173 IOCS_B_PRINT("Invalid disk.\r\n"); 174 return 0; 175 } 176 177 for (i = 1; i < NDOSPART; i++) { 178 if (label->dosparts[i].dp_flag == PART_BOOTABLE) 179 break; 180 else if (label->dosparts[i].dp_flag == PART_INUSE) 181 firstinuse = i; 182 } 183 if (i >= NDOSPART && firstinuse >= 0) 184 i = firstinuse; 185 if (i < NDOSPART) { 186 unsigned int start = label->dosparts[i].dp_start; 187 unsigned int start1 = start << (2-size); 188 int r; 189 if ((start1 & 0x1fffff) == 0x1fffff) 190 r = IOCS_S_READ(start1, 191 8>>size, 192 scsiid, 193 size, 194 (void*) 0x2400); 195 else 196 r = IOCS_S_READEXT(start1, 197 8>>size, 198 scsiid, 199 size, 200 (void*) 0x2400); 201 if (r < 0) { 202 IOCS_B_PRINT ("Error in reading.\r\n"); 203 return 0; 204 } 205 if (*((char*) 0x2400) != 0x60) { 206 IOCS_B_PRINT("Invalid disk.\r\n"); 207 return 0; 208 } 209 __asm volatile ("movl %0,%%d4\n\t" 210 "movl %1,%%d2\n\t" 211 "jsr 0x2400" 212 : 213 : "g" (scsiid), "g"(start) 214 : "d4"); 215 return 0; 216 } 217 IOCS_B_PRINT ("No bootable partition.\r\n"); 218 return 0; 219 } 220 221 return 0; 222 } 223