1 // SPDX-License-Identifier: GPL-2.0 1 2 /* 3 * Copyright (C) 1995, 1996 Gero Kuhlmann <g 4 * 5 * Allow an NFS filesystem to be mounted as r 6 * (1) Use the IP autoconfig mechanism to 7 * (2) Construct the device string and the 8 * option 17 and/or kernel command lin 9 * (3) When mount_root() sets up the root 10 * to the NFS client's regular mount i 11 * 12 * 13 * Changes: 14 * 15 * Alan Cox : Removed get_ad 16 * Alan Cox : Reformatted a 17 * Gero Kuhlmann : Code cleanup 18 * Michael Rausch : Fixed recognit 19 * Martin Mares : (2.0) Auto-configura 20 * Martin Mares : Manual selecti 21 * Martin Mares : Using network 22 * allowing the d 23 * for normal ope 24 * Martin Mares : Randomized tim 25 * installed to m 26 * Martin Mares : Code cleanup. 27 * Martin Mares : (2.1) BOOTP and RARP 28 * Martin Mares : Server hostnam 29 * Gerd Knorr : Fixed wired in 30 * Martin Mares : (2.2) "0.0.0.0" addr 31 * Martin Mares : RARP replies n 32 * Gero Kuhlmann : (2.3) Some bug fixes 33 * send me your n 34 * Linus so that 35 * _afterwards_ - 36 * Gero Kuhlmann : Last changes o 37 * Gero Kuhlmann : RARP replies a 38 * again. However 39 * different RARP 40 * Gero Kuhlmann : "0.0.0.0" addr 41 * now mapped to 42 * Gero Kuhlmann : Fixed a bug wh 43 * from being use 44 * Andy Walker : Allow to speci 45 * without giving 46 * Swen Thümmler : Allow to speci 47 * without giving 48 * for domainname 49 * DNS domain!). 50 * Jacek Zapala : Fixed a bug wh 51 * from nfsroot p 52 * Olaf Kirch : Adapted to new 53 * Jakub Jelinek : Free used code 54 * Marko Kohtala : Fixed some bug 55 * Martin Mares : Debug message 56 * Martin Mares : Changed to use 57 * code. BOOTP an 58 * Martin Mares : Default path n 59 * host IP addres 60 * address anyway 61 * Martin Mares : Use root_serve 62 * Martin Mares : Rewrote parame 63 * correct overri 64 * Trond Myklebust : Add in prelimi 65 * Fix bug in roo 66 * is NOT for the 67 * Hua Qin : Support for mo 68 * NFS over TCP. 69 * Fabian Frederick: Option parser 70 * Chuck Lever : Use super.c's 71 * Chuck Lever : Add "nfsrootde 72 */ 73 74 #include <linux/types.h> 75 #include <linux/string.h> 76 #include <linux/init.h> 77 #include <linux/nfs.h> 78 #include <linux/nfs_fs.h> 79 #include <linux/utsname.h> 80 #include <linux/root_dev.h> 81 #include <net/ipconfig.h> 82 83 #include "internal.h" 84 85 #define NFSDBG_FACILITY NFSDBG_ROOT 86 87 /* Default path we try to mount. "%s" gets rep 88 #define NFS_ROOT "/tftpboot/%s" 89 90 /* Default NFSROOT mount options. */ 91 #if defined(CONFIG_NFS_V2) 92 #define NFS_DEF_OPTIONS "vers=2,tcp,rs 93 #elif defined(CONFIG_NFS_V3) 94 #define NFS_DEF_OPTIONS "vers=3,tcp,rs 95 #else 96 #define NFS_DEF_OPTIONS "vers=4,tcp,rs 97 #endif 98 99 /* Parameters passed from the kernel command l 100 static char nfs_root_parms[NFS_MAXPATHLEN + 1] 101 102 /* Text-based mount options passed to super.c 103 static char nfs_root_options[256] __initdata = 104 105 /* Address of NFS server */ 106 static __be32 servaddr __initdata = htonl(INAD 107 108 /* Name of directory to mount */ 109 static char nfs_export_path[NFS_MAXPATHLEN + 1 110 111 /* server:export path string passed to super.c 112 static char nfs_root_device[NFS_MAXPATHLEN + 1 113 114 #ifdef NFS_DEBUG 115 /* 116 * When the "nfsrootdebug" kernel command line 117 * enable debugging messages for NFSROOT. 118 */ 119 static int __init nfs_root_debug(char *__unuse 120 { 121 nfs_debug |= NFSDBG_ROOT | NFSDBG_MOUN 122 return 1; 123 } 124 125 __setup("nfsrootdebug", nfs_root_debug); 126 #endif 127 128 /* 129 * Parse NFS server and directory information 130 * command line. 131 * 132 * nfsroot=[<server-ip>:]<root-dir>[,<nfs-opt 133 * 134 * If there is a "%s" token in the <root-dir> 135 * by the ASCII-representation of the client' 136 */ 137 static int __init nfs_root_setup(char *line) 138 { 139 ROOT_DEV = Root_NFS; 140 141 if (line[0] == '/' || line[0] == ',' | 142 strscpy(nfs_root_parms, line, 143 } else { 144 size_t n = strlen(line) + size 145 if (n >= sizeof(nfs_root_parms 146 line[sizeof(nfs_root_p 147 sprintf(nfs_root_parms, NFS_RO 148 } 149 150 /* 151 * Extract the IP address of the NFS s 152 * root file system, if one was specif 153 * 154 * Note: root_nfs_parse_addr() removes 155 * nfs_root_parms, if it exists. 156 */ 157 root_server_addr = root_nfs_parse_addr 158 159 return 1; 160 } 161 162 __setup("nfsroot=", nfs_root_setup); 163 164 static int __init root_nfs_copy(char *dest, co 165 const siz 166 { 167 if (strscpy(dest, src, destlen) == -E2 168 return -1; 169 return 0; 170 } 171 172 static int __init root_nfs_cat(char *dest, con 173 const size_t de 174 { 175 size_t len = strlen(dest); 176 177 if (len && dest[len - 1] != ',') 178 if (strlcat(dest, ",", destlen 179 return -1; 180 181 if (strlcat(dest, src, destlen) >= des 182 return -1; 183 return 0; 184 } 185 186 /* 187 * Parse out root export path and mount option 188 * passed-in string @incoming. 189 * 190 * Copy the export path into @exppath. 191 */ 192 static int __init root_nfs_parse_options(char 193 const 194 { 195 char *p; 196 197 /* 198 * Set the NFS remote path 199 */ 200 p = strsep(&incoming, ","); 201 if (*p != '\0' && strcmp(p, "default") 202 if (root_nfs_copy(exppath, p, 203 return -1; 204 205 /* 206 * @incoming now points to the rest of 207 * contains something, append it to ou 208 */ 209 if (incoming != NULL && *incoming != ' 210 if (root_nfs_cat(nfs_root_opti 211 212 return -1; 213 return 0; 214 } 215 216 /* 217 * Decode the export directory path name and 218 * the kernel command line. This has to be d 219 * use a dynamically acquired client IP addre 220 * root directory path. 221 * 222 * Returns zero if successful; otherwise -1 i 223 */ 224 static int __init root_nfs_data(char *cmdline) 225 { 226 char mand_options[sizeof("nolock,addr= 227 int len, retval = -1; 228 char *tmp = NULL; 229 const size_t tmplen = sizeof(nfs_expor 230 231 tmp = kzalloc(tmplen, GFP_KERNEL); 232 if (tmp == NULL) 233 goto out_nomem; 234 strcpy(tmp, NFS_ROOT); 235 236 if (root_server_path[0] != '\0') { 237 dprintk("Root-NFS: DHCPv4 opti 238 root_server_path); 239 if (root_nfs_parse_options(roo 240 goto out_optionstoolon 241 } 242 243 if (cmdline[0] != '\0') { 244 dprintk("Root-NFS: nfsroot=%s\ 245 if (root_nfs_parse_options(cmd 246 goto out_optionstoolon 247 } 248 249 /* 250 * Append mandatory options for nfsroo 251 * what has come before 252 */ 253 snprintf(mand_options, sizeof(mand_opt 254 &servaddr); 255 if (root_nfs_cat(nfs_root_options, man 256 257 goto out_optionstoolong; 258 259 /* 260 * Set up nfs_root_device. For NFS mo 261 * 262 * server:/path 263 * 264 * At this point, utsname()->nodename 265 * IP address or hostname, set by ipco 266 * in tmp, substitute the nodename, th 267 * mess into nfs_root_device. 268 */ 269 len = snprintf(nfs_export_path, sizeof 270 tmp, utsname() 271 if (len >= (int)sizeof(nfs_export_path 272 goto out_devnametoolong; 273 len = snprintf(nfs_root_device, sizeof 274 "%pI4:%s", &se 275 if (len >= (int)sizeof(nfs_root_device 276 goto out_devnametoolong; 277 278 retval = 0; 279 280 out: 281 kfree(tmp); 282 return retval; 283 out_nomem: 284 printk(KERN_ERR "Root-NFS: could not a 285 goto out; 286 out_optionstoolong: 287 printk(KERN_ERR "Root-NFS: mount optio 288 goto out; 289 out_devnametoolong: 290 printk(KERN_ERR "Root-NFS: root device 291 goto out; 292 } 293 294 /** 295 * nfs_root_data - Return prepared 'data' for 296 * @root_device: OUT: address of string contai 297 * @root_data: OUT: address of string containi 298 * 299 * Returns zero and sets @root_device and @roo 300 * otherwise -1 is returned. 301 */ 302 int __init nfs_root_data(char **root_device, c 303 { 304 servaddr = root_server_addr; 305 if (servaddr == htonl(INADDR_NONE)) { 306 printk(KERN_ERR "Root-NFS: no 307 return -1; 308 } 309 310 if (root_nfs_data(nfs_root_parms) < 0) 311 return -1; 312 313 *root_device = nfs_root_device; 314 *root_data = nfs_root_options; 315 return 0; 316 } 317
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.