1 /* $NetBSD: boot1.c,v 1.20 2011/01/06 01:08:48 jakllsch 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.20 2011/01/06 01:08:48 jakllsch 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 daddr_t bios_sector; 48 49 static struct biosdisk_ll d; 50 51 const char *boot1(uint32_t, uint64_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, uint64_t *sector) 64 { 65 struct stat sb; 66 int fd; 67 68 bios_sector = *sector; 69 d.dev = biosdev; 70 71 putstr("\r\nNetBSD/x86 " STR(FS) " Primary Bootstrap\r\n"); 72 73 if (set_geometry(&d, NULL)) 74 return "set_geometry\r\n"; 75 76 /* 77 * We default to the filesystem at the start of the 78 * MBR partition 79 */ 80 fd = ob(); 81 if (fd != -1) 82 goto done; 83 /* 84 * Maybe the filesystem is enclosed in a raid set. 85 * add in size of raidframe header and try again. 86 * (Maybe this should only be done if the filesystem 87 * magic number is absent.) 88 */ 89 bios_sector += RF_PROTECTED_SECTORS; 90 fd = ob(); 91 if (fd != -1) 92 goto done; 93 /* 94 * Nothing at the start of the MBR partition, fallback on 95 * partition 'a' from the disklabel in this MBR partition. 96 */ 97 if (ptn_disklabel.d_magic != DISKMAGIC || 98 ptn_disklabel.d_magic2 != DISKMAGIC || 99 ptn_disklabel.d_partitions[0].p_fstype == FS_UNUSED) 100 goto done; 101 bios_sector = ptn_disklabel.d_partitions[0].p_offset; 102 *sector = bios_sector; 103 if (ptn_disklabel.d_partitions[0].p_fstype == FS_RAID) 104 bios_sector += RF_PROTECTED_SECTORS; 105 106 fd = ob(); 107 108 done: 109 /* if we fail here, so will fstat, so keep going */ 110 if (fd == -1 || fstat(fd, &sb) == -1) 111 return "Can't open /boot\r\n"; 112 113 biosdev = (uint32_t)sb.st_size; 114 #if 0 115 if (biosdev > SECONDARY_MAX_LOAD) 116 return "/boot too large\r\n"; 117 #endif 118 119 if (read(fd, (void *)SECONDARY_LOAD_ADDRESS, biosdev) != biosdev) 120 return "/boot load failed\r\n"; 121 122 if (*(uint32_t *)(SECONDARY_LOAD_ADDRESS + 4) != X86_BOOT_MAGIC_2) 123 return "Invalid /boot file format\r\n"; 124 125 /* We need to jump to the secondary bootstrap in realmode */ 126 return 0; 127 } 128 129 int 130 blkdevstrategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize) 131 { 132 if (flag != F_READ) 133 return EROFS; 134 135 if (size & (BIOSDISK_DEFAULT_SECSIZE - 1)) 136 return EINVAL; 137 138 if (rsize) 139 *rsize = size; 140 141 if (size != 0 && readsects(&d, bios_sector + dblk, 142 size / BIOSDISK_DEFAULT_SECSIZE, 143 buf, 1) != 0) 144 return EIO; 145 146 return 0; 147 } 148