1/* $NetBSD: devopen.c,v 1.8 2009/03/18 17:06:44 cegger Exp $ */ 2 3/* 4 * Copyright 2001, 2002 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38#include <sys/param.h> 39#include <lib/libsa/stand.h> 40#include <netinet/in.h> 41#include <netinet/in_systm.h> 42#include <net.h> 43 44#include <libi386.h> 45#ifdef _STANDALONE 46#include <lib/libkern/libkern.h> 47#include <bootinfo.h> 48#else 49#include <string.h> 50#endif 51 52#include "pxeboot.h" 53 54#ifdef _STANDALONE 55struct btinfo_bootpath bibp; 56#endif 57 58/* 59 * Open the "device" named by the combined file system/file name 60 * given as the fname arg. Format is: 61 * 62 * nfs:netbsd 63 * tftp:netbsd 64 * netbsd 65 * 66 * If no file system is specified, we default to the first in the 67 * file system table (which ought to be NFS). 68 * 69 * We always open just one device (the PXE netif). 70 */ 71int 72devopen(struct open_file *f, const char *fname, char **file) 73{ 74 struct devsw *dp; 75 char *filename; 76 size_t fsnamelen; 77 int i, error; 78 79 dp = &devsw[0]; 80 81 /* Set the default boot file system. */ 82 memcpy(file_system, pxeboot_fstab[0].fst_ops, sizeof(struct fs_ops)); 83 84 /* if we got passed a filename, pass it to the BOOTP server */ 85 if (fname) 86 strncpy(bootfile, fname, FNAME_SIZE); 87 88 /* Open the device; this might give us a boot file name. */ 89 error = (*dp->dv_open)(f, NULL); 90 if (error) 91 return (error); 92 93 f->f_dev = dp; 94 95 /* 96 * If the DHCP server provided a file name: 97 * - If it contains a ":", assume it points to a NetBSD kernel. 98 * - If not, assume that the DHCP server was not able to pass 99 * a separate filename for the kernel. (The name probably 100 * was the same as used to load "pxeboot".) Ignore it and 101 * use the default in this case. 102 * So we cater to simple DHCP servers while being able to 103 * use the power of conditional behaviour in modern ones. 104 */ 105 if (strchr(bootfile, ':')) 106 fname = bootfile; 107 108 filename = (fname ? strchr(fname, ':') : NULL); 109 if (filename != NULL) { 110 fsnamelen = (size_t)((const char *)filename - fname); 111 for (i = 0; i < npxeboot_fstab; i++) { 112 if (strncmp(fname, pxeboot_fstab[i].fst_name, 113 fsnamelen) == 0) { 114 memcpy(file_system, pxeboot_fstab[i].fst_ops, 115 sizeof(struct fs_ops)); 116 break; 117 } 118 } 119 if (i == npxeboot_fstab) { 120 printf("Invalid file system type specified in %s\n", 121 fname); 122 error = EINVAL; 123 goto bad; 124 } 125 filename++; 126 if (filename[0] == '\0') { 127 printf("No file specified in %s\n", fname); 128 error = EINVAL; 129 goto bad; 130 } 131 } else 132 filename = (char *)fname; 133 134 *file = filename; 135 136#ifdef _STANDALONE 137 strncpy(bibp.bootpath, filename, sizeof(bibp.bootpath)); 138 BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp)); 139#endif 140 141 return (0); 142 bad: 143 (*dp->dv_close)(f); 144 f->f_dev = NULL; 145 return (error); 146} 147