1 /* $NetBSD: boot1.c,v 1.17 2008/04/30 16:18:26 ad Exp $ */ 2 3 /*- 4 * Copyright (c) 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by David Laight. 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/cdefs.h> 33 __RCSID("$NetBSD: boot1.c,v 1.17 2008/04/30 16:18:26 ad Exp $"); 34 35 #include <lib/libsa/stand.h> 36 #include <lib/libkern/libkern.h> 37 #include <biosdisk_ll.h> 38 39 #include <sys/param.h> 40 #include <sys/bootblock.h> 41 #include <sys/disklabel.h> 42 #include <dev/raidframe/raidframevar.h> /* For RF_PROTECTED_SECTORS */ 43 44 #define XSTR(x) #x 45 #define STR(x) XSTR(x) 46 47 static uint32_t bios_sector; 48 49 static struct biosdisk_ll d; 50 51 const char *boot1(uint32_t, uint32_t *); 52 extern void putstr(const char *); 53 54 extern struct disklabel ptn_disklabel; 55 56 static int 57 ob(void) 58 { 59 return open("boot", 0); 60 } 61 62 const char * 63 boot1(uint32_t biosdev, uint32_t *sector) 64 { 65 struct stat sb; 66 int fd; 67 68 bios_sector = *sector; 69 d.dev = biosdev; 70 71 #ifdef SHOW_BANNER 72 putstr("\r\nNetBSD/x86 " STR(FS) " Primary Bootstrap\r\n"); 73 #endif 74 75 if (set_geometry(&d, NULL)) 76 return "set_geometry\r\n"; 77 78 /* 79 * We default to the filesystem at the start of the 80 * MBR partition 81 */ 82 fd = ob(); 83 if (fd != -1) 84 goto done; 85 /* 86 * Maybe the filesystem is enclosed in a raid set. 87 * add in size of raidframe header and try again. 88 * (Maybe this should only be done if the filesystem 89 * magic number is absent.) 90 */ 91 bios_sector += RF_PROTECTED_SECTORS; 92 fd = ob(); 93 if (fd != -1) 94 goto done; 95 /* 96 * Nothing at the start of the MBR partition, fallback on 97 * partition 'a' from the disklabel in this MBR partition. 98 */ 99 if (ptn_disklabel.d_magic != DISKMAGIC || 100 ptn_disklabel.d_magic2 != DISKMAGIC || 101 ptn_disklabel.d_partitions[0].p_fstype == FS_UNUSED) 102 goto done; 103 bios_sector = ptn_disklabel.d_partitions[0].p_offset; 104 *sector = bios_sector; 105 if (ptn_disklabel.d_partitions[0].p_fstype == FS_RAID) 106 bios_sector += RF_PROTECTED_SECTORS; 107 108 fd = ob(); 109 110 done: 111 /* if we fail here, so will fstat, so keep going */ 112 if (fstat(fd, &sb) == -1) { 113 return "Can't open /boot\r\n"; 114 } 115 116 biosdev = (uint32_t)sb.st_size; 117 #if 0 118 if (biosdev > SECONDARY_MAX_LOAD) 119 return "/boot too large\r\n"; 120 #endif 121 122 if (read(fd, (void *)SECONDARY_LOAD_ADDRESS, biosdev) != biosdev) 123 return "/boot load failed\r\n"; 124 125 if (*(uint32_t *)(SECONDARY_LOAD_ADDRESS + 4) != X86_BOOT_MAGIC_2) 126 return "Invalid /boot file format\r\n"; 127 128 /* We need to jump to the secondary bootstrap in realmode */ 129 return 0; 130 } 131 132 int 133 blkdevstrategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize) 134 { 135 if (flag != F_READ) 136 return EROFS; 137 138 if (size & (BIOSDISK_DEFAULT_SECSIZE - 1)) 139 return EINVAL; 140 141 if (rsize) 142 *rsize = size; 143 144 if (size != 0 && readsects(&d, bios_sector + dblk, 145 size / BIOSDISK_DEFAULT_SECSIZE, 146 buf, 1) != 0) 147 return EIO; 148 149 return 0; 150 } 151