1*58a2b000SEvgeniy Ivanov /* $NetBSD: boot1.c,v 1.20 2011/01/06 01:08:48 jakllsch Exp $ */ 2*58a2b000SEvgeniy Ivanov 3*58a2b000SEvgeniy Ivanov /*- 4*58a2b000SEvgeniy Ivanov * Copyright (c) 2003 The NetBSD Foundation, Inc. 5*58a2b000SEvgeniy Ivanov * All rights reserved. 6*58a2b000SEvgeniy Ivanov * 7*58a2b000SEvgeniy Ivanov * This code is derived from software contributed to The NetBSD Foundation 8*58a2b000SEvgeniy Ivanov * by David Laight. 9*58a2b000SEvgeniy Ivanov * 10*58a2b000SEvgeniy Ivanov * Redistribution and use in source and binary forms, with or without 11*58a2b000SEvgeniy Ivanov * modification, are permitted provided that the following conditions 12*58a2b000SEvgeniy Ivanov * are met: 13*58a2b000SEvgeniy Ivanov * 1. Redistributions of source code must retain the above copyright 14*58a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer. 15*58a2b000SEvgeniy Ivanov * 2. Redistributions in binary form must reproduce the above copyright 16*58a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer in the 17*58a2b000SEvgeniy Ivanov * documentation and/or other materials provided with the distribution. 18*58a2b000SEvgeniy Ivanov * 19*58a2b000SEvgeniy Ivanov * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20*58a2b000SEvgeniy Ivanov * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21*58a2b000SEvgeniy Ivanov * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22*58a2b000SEvgeniy Ivanov * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23*58a2b000SEvgeniy Ivanov * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*58a2b000SEvgeniy Ivanov * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*58a2b000SEvgeniy Ivanov * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*58a2b000SEvgeniy Ivanov * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*58a2b000SEvgeniy Ivanov * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*58a2b000SEvgeniy Ivanov * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*58a2b000SEvgeniy Ivanov * POSSIBILITY OF SUCH DAMAGE. 30*58a2b000SEvgeniy Ivanov */ 31*58a2b000SEvgeniy Ivanov 32*58a2b000SEvgeniy Ivanov #include <sys/cdefs.h> 33*58a2b000SEvgeniy Ivanov __RCSID("$NetBSD: boot1.c,v 1.20 2011/01/06 01:08:48 jakllsch Exp $"); 34*58a2b000SEvgeniy Ivanov 35*58a2b000SEvgeniy Ivanov #include <lib/libsa/stand.h> 36*58a2b000SEvgeniy Ivanov #include <lib/libkern/libkern.h> 37*58a2b000SEvgeniy Ivanov #include <biosdisk_ll.h> 38*58a2b000SEvgeniy Ivanov 39*58a2b000SEvgeniy Ivanov #include <sys/param.h> 40*58a2b000SEvgeniy Ivanov #include <sys/bootblock.h> 41*58a2b000SEvgeniy Ivanov #include <sys/disklabel.h> 42*58a2b000SEvgeniy Ivanov #include <dev/raidframe/raidframevar.h> /* For RF_PROTECTED_SECTORS */ 43*58a2b000SEvgeniy Ivanov 44*58a2b000SEvgeniy Ivanov #define XSTR(x) #x 45*58a2b000SEvgeniy Ivanov #define STR(x) XSTR(x) 46*58a2b000SEvgeniy Ivanov 47*58a2b000SEvgeniy Ivanov static daddr_t bios_sector; 48*58a2b000SEvgeniy Ivanov 49*58a2b000SEvgeniy Ivanov static struct biosdisk_ll d; 50*58a2b000SEvgeniy Ivanov 51*58a2b000SEvgeniy Ivanov const char *boot1(uint32_t, uint64_t *); 52*58a2b000SEvgeniy Ivanov extern void putstr(const char *); 53*58a2b000SEvgeniy Ivanov 54*58a2b000SEvgeniy Ivanov extern struct disklabel ptn_disklabel; 55*58a2b000SEvgeniy Ivanov 56*58a2b000SEvgeniy Ivanov static int 57*58a2b000SEvgeniy Ivanov ob(void) 58*58a2b000SEvgeniy Ivanov { 59*58a2b000SEvgeniy Ivanov return open("boot", 0); 60*58a2b000SEvgeniy Ivanov } 61*58a2b000SEvgeniy Ivanov 62*58a2b000SEvgeniy Ivanov const char * 63*58a2b000SEvgeniy Ivanov boot1(uint32_t biosdev, uint64_t *sector) 64*58a2b000SEvgeniy Ivanov { 65*58a2b000SEvgeniy Ivanov struct stat sb; 66*58a2b000SEvgeniy Ivanov int fd; 67*58a2b000SEvgeniy Ivanov 68*58a2b000SEvgeniy Ivanov bios_sector = *sector; 69*58a2b000SEvgeniy Ivanov d.dev = biosdev; 70*58a2b000SEvgeniy Ivanov 71*58a2b000SEvgeniy Ivanov putstr("\r\nNetBSD/x86 " STR(FS) " Primary Bootstrap\r\n"); 72*58a2b000SEvgeniy Ivanov 73*58a2b000SEvgeniy Ivanov if (set_geometry(&d, NULL)) 74*58a2b000SEvgeniy Ivanov return "set_geometry\r\n"; 75*58a2b000SEvgeniy Ivanov 76*58a2b000SEvgeniy Ivanov /* 77*58a2b000SEvgeniy Ivanov * We default to the filesystem at the start of the 78*58a2b000SEvgeniy Ivanov * MBR partition 79*58a2b000SEvgeniy Ivanov */ 80*58a2b000SEvgeniy Ivanov fd = ob(); 81*58a2b000SEvgeniy Ivanov if (fd != -1) 82*58a2b000SEvgeniy Ivanov goto done; 83*58a2b000SEvgeniy Ivanov /* 84*58a2b000SEvgeniy Ivanov * Maybe the filesystem is enclosed in a raid set. 85*58a2b000SEvgeniy Ivanov * add in size of raidframe header and try again. 86*58a2b000SEvgeniy Ivanov * (Maybe this should only be done if the filesystem 87*58a2b000SEvgeniy Ivanov * magic number is absent.) 88*58a2b000SEvgeniy Ivanov */ 89*58a2b000SEvgeniy Ivanov bios_sector += RF_PROTECTED_SECTORS; 90*58a2b000SEvgeniy Ivanov fd = ob(); 91*58a2b000SEvgeniy Ivanov if (fd != -1) 92*58a2b000SEvgeniy Ivanov goto done; 93*58a2b000SEvgeniy Ivanov 94*58a2b000SEvgeniy Ivanov #ifdef BOOT_FROM_MINIXFS3 95*58a2b000SEvgeniy Ivanov bios_sector -= RF_PROTECTED_SECTORS; 96*58a2b000SEvgeniy Ivanov bios_sector += 32; /* XXX put somewhere as constant */ 97*58a2b000SEvgeniy Ivanov *sector = bios_sector; 98*58a2b000SEvgeniy Ivanov 99*58a2b000SEvgeniy Ivanov fd = ob(); 100*58a2b000SEvgeniy Ivanov if (fd != -1) 101*58a2b000SEvgeniy Ivanov goto done; 102*58a2b000SEvgeniy Ivanov #endif 103*58a2b000SEvgeniy Ivanov 104*58a2b000SEvgeniy Ivanov /* 105*58a2b000SEvgeniy Ivanov * Nothing at the start of the MBR partition, fallback on 106*58a2b000SEvgeniy Ivanov * partition 'a' from the disklabel in this MBR partition. 107*58a2b000SEvgeniy Ivanov */ 108*58a2b000SEvgeniy Ivanov if (ptn_disklabel.d_magic != DISKMAGIC || 109*58a2b000SEvgeniy Ivanov ptn_disklabel.d_magic2 != DISKMAGIC || 110*58a2b000SEvgeniy Ivanov ptn_disklabel.d_partitions[0].p_fstype == FS_UNUSED) 111*58a2b000SEvgeniy Ivanov goto done; 112*58a2b000SEvgeniy Ivanov bios_sector = ptn_disklabel.d_partitions[0].p_offset; 113*58a2b000SEvgeniy Ivanov *sector = bios_sector; 114*58a2b000SEvgeniy Ivanov if (ptn_disklabel.d_partitions[0].p_fstype == FS_RAID) 115*58a2b000SEvgeniy Ivanov bios_sector += RF_PROTECTED_SECTORS; 116*58a2b000SEvgeniy Ivanov 117*58a2b000SEvgeniy Ivanov fd = ob(); 118*58a2b000SEvgeniy Ivanov 119*58a2b000SEvgeniy Ivanov done: 120*58a2b000SEvgeniy Ivanov /* if we fail here, so will fstat, so keep going */ 121*58a2b000SEvgeniy Ivanov if (fd == -1 || fstat(fd, &sb) == -1) 122*58a2b000SEvgeniy Ivanov return "Can't open /boot\r\n"; 123*58a2b000SEvgeniy Ivanov 124*58a2b000SEvgeniy Ivanov biosdev = (uint32_t)sb.st_size; 125*58a2b000SEvgeniy Ivanov #if 0 126*58a2b000SEvgeniy Ivanov if (biosdev > SECONDARY_MAX_LOAD) 127*58a2b000SEvgeniy Ivanov return "/boot too large\r\n"; 128*58a2b000SEvgeniy Ivanov #endif 129*58a2b000SEvgeniy Ivanov 130*58a2b000SEvgeniy Ivanov if (read(fd, (void *)SECONDARY_LOAD_ADDRESS, biosdev) != biosdev) 131*58a2b000SEvgeniy Ivanov return "/boot load failed\r\n"; 132*58a2b000SEvgeniy Ivanov 133*58a2b000SEvgeniy Ivanov if (*(uint32_t *)(SECONDARY_LOAD_ADDRESS + 4) != X86_BOOT_MAGIC_2) 134*58a2b000SEvgeniy Ivanov return "Invalid /boot file format\r\n"; 135*58a2b000SEvgeniy Ivanov 136*58a2b000SEvgeniy Ivanov /* We need to jump to the secondary bootstrap in realmode */ 137*58a2b000SEvgeniy Ivanov return 0; 138*58a2b000SEvgeniy Ivanov } 139*58a2b000SEvgeniy Ivanov 140*58a2b000SEvgeniy Ivanov int 141*58a2b000SEvgeniy Ivanov blkdevstrategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize) 142*58a2b000SEvgeniy Ivanov { 143*58a2b000SEvgeniy Ivanov if (flag != F_READ) 144*58a2b000SEvgeniy Ivanov return EROFS; 145*58a2b000SEvgeniy Ivanov 146*58a2b000SEvgeniy Ivanov if (size & (BIOSDISK_DEFAULT_SECSIZE - 1)) 147*58a2b000SEvgeniy Ivanov return EINVAL; 148*58a2b000SEvgeniy Ivanov 149*58a2b000SEvgeniy Ivanov if (rsize) 150*58a2b000SEvgeniy Ivanov *rsize = size; 151*58a2b000SEvgeniy Ivanov 152*58a2b000SEvgeniy Ivanov if (size != 0 && readsects(&d, bios_sector + dblk, 153*58a2b000SEvgeniy Ivanov size / BIOSDISK_DEFAULT_SECSIZE, 154*58a2b000SEvgeniy Ivanov buf, 1) != 0) 155*58a2b000SEvgeniy Ivanov return EIO; 156*58a2b000SEvgeniy Ivanov 157*58a2b000SEvgeniy Ivanov return 0; 158*58a2b000SEvgeniy Ivanov } 159