1#!/usr/bin/awk - 2# 3# $NetBSD: MAKEDEV.awk,v 1.21 2010/03/30 07:30:03 mrg Exp $ 4# 5# Copyright (c) 2003 The NetBSD Foundation, Inc. 6# All rights reserved. 7# 8# This code is derived from software contributed to The NetBSD Foundation 9# by Jaromir Dolecek. 10# 11# Redistribution and use in source and binary forms, with or without 12# modification, are permitted provided that the following conditions 13# are met: 14# 1. Redistributions of source code must retain the above copyright 15# notice, this list of conditions and the following disclaimer. 16# 2. Redistributions in binary form must reproduce the above copyright 17# notice, this list of conditions and the following disclaimer in the 18# documentation and/or other materials provided with the distribution. 19# 20# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30# POSSIBILITY OF SUCH DAMAGE. 31# 32 33# Script to generate platform MAKEDEV script from MI template, MD 34# MAKEDEV.conf and MD/MI major lists 35# 36# Uses environment variables MACHINE/MACHINE_ARCH to select 37# appropriate files, and NETBSDSRCDIR to get root of source tree. 38 39BEGIN { 40 # top of source tree, used to find major number list in kernel 41 # sources 42 machine = ENVIRON["MACHINE"] 43 maarch = ENVIRON["MACHINE_ARCH"] 44 srcdir = ENVIRON["NETBSDSRCDIR"] 45 if (!machine || !maarch || !srcdir) { 46 print "ERROR: 'MACHINE', 'MACHINE_ARCH' and 'NETBSDSRCDIR' must be set in environment" > "/dev/stderr" 47 exit 1 48 } 49 top = srcdir "/sys/" 50 if (system("test -d '" top "'") != 0) { 51 print "ERROR: can't find top of kernel source tree ('" top "' not a directory)" > "/dev/stderr" 52 exit 1 53 } 54 55 56 # file with major definitions 57 majors[0] = "conf/majors" 58 if ((maarch == "arm" || maarch == "armeb") && system("test -f '" top "arch/" machine "/conf/majors." machine "'") != 0) 59 majors[1] = "arch/arm/conf/majors.arm32"; 60 else if (machine == "sbmips") 61 majors[1] = "arch/evbmips/conf/majors.evbmips"; 62 else if ((maarch == "powerpc" || maarch == "powerpc64") && system("test -f '" top "arch/" machine "/conf/majors." machine "'") != 0) 63 majors[1] = "arch/powerpc/conf/majors.powerpc"; 64 else 65 majors[1] = "arch/" machine "/conf/majors." machine; 66 67 # process all files with majors and fill the chr[] and blk[] 68 # arrays, used in template processing 69 for (m in majors) { 70 file = top majors[m] 71 if (system("test -f '" file "'") != 0) { 72 print "ERROR: can't find majors file '" file "'" > "/dev/stderr" 73 exit 1 74 } 75 while (getline < file) { 76 if ($1 == "device-major") { 77 if ($3 == "char") { 78 chr[$2] = $4 79 if ($5 == "block") 80 blk[$2] = $6 81 } else if ($3 == "block") 82 blk[$2] = $4 83 } 84 } 85 close(file) 86 } 87 CONSOLE_CMAJOR = chr["cons"] 88 if (CONSOLE_CMAJOR == "") { 89 print "ERROR: no entry for 'cons' in majors file" > "/dev/stderr" 90 exit 1 91 } 92 93 # read MD config file for MD device targets 94 cfgfile = srcdir "/etc/etc." machine "/MAKEDEV.conf" 95 if (system("test -f '" cfgfile "'") != 0) { 96 print "ERROR: no platform MAKEDEV.conf - '" cfgfile "' doesn't exist" > "/dev/stderr" 97 exit 1 98 } 99 # skip first two lines 100 getline CONFRCSID < cfgfile # RCS Id 101 getline < cfgfile # blank line 102 MDDEV = 0 # MD device targets 103 while (getline < cfgfile) { 104 if (MDDEV) 105 MDDEV = MDDEV "\n" $0 106 else 107 MDDEV = $0 108 } 109 close(cfgfile) 110 111 # determine number of partitions used by platform 112 # there are three variants in tree: 113 # 1. MAXPARTITIONS = 8 114 # 2. MAXPARTITIONS = 16 with no back compat mapping 115 # 3. MAXPARTITIONS = 16 with back compat with old limit of 8 116 # currently all archs, which moved from 8->16 use same 117 # scheme for mapping disk minors, high minor offset 118 # if this changes, the below needs to be adjusted and 119 # additional makedisk_p16foo needs to be added 120 incdir = machine 121 diskpartitions = 0 122 diskbackcompat = 0 123 while (1) { 124 inc = top "arch/" incdir "/include/disklabel.h" 125 if (system("test -f '" inc "'") != 0) { 126 print "ERROR: can't find kernel include file '" inc "'" > "/dev/stderr" 127 exit 1 128 } 129 incdir = 0 130 while (getline < inc) { 131 if ($1 == "#define" && $2 == "MAXPARTITIONS") 132 diskpartitions = $3 133 else if ($1 == "#define" && $2 == "OLDMAXPARTITIONS") 134 diskbackcompat = $3 135 else if ($1 == "#define" && $2 == "RAW_PART") 136 RAWDISK_OFF = $3 137 else if ($1 == "#include" && 138 $2 ~ "<.*/disklabel.h>" && 139 $2 !~ ".*nbinclude.*") 140 { 141 # wrapper, switch to the right file 142 incdir = substr($2, 2) 143 sub("/.*", "", incdir) 144 break; 145 } 146 } 147 close(inc) 148 149 if (diskpartitions) 150 break; 151 152 if (!incdir) { 153 print "ERROR: can't determine MAXPARTITIONS from include file '" inc "'" > "/dev/stderr" 154 exit 1 155 } 156 } 157 MKDISK = "makedisk_p" diskpartitions # routine to create disk devs 158 DISKMINOROFFSET = diskpartitions 159 if (diskbackcompat) { 160 MKDISK = MKDISK "high" 161 DISKMINOROFFSET = diskbackcompat 162 } 163 RAWDISK_NAME = sprintf("%c", 97 + RAWDISK_OFF) # a+offset 164 165 # read etc/master.passwd for user name->UID mapping 166 idfile = srcdir "/etc/master.passwd" 167 if (system("test -f '" idfile "'") != 0) { 168 print "ERROR: can't find password file '" idfile "'" > "/dev/stderr" 169 exit 1 170 } 171 oldFS=FS 172 FS=":" 173 while (getline < idfile) { 174 uid[$1] = $3 175 } 176 close(idfile) 177 FS=oldFS 178 179 # read etc/group for group name->GID mapping 180 idfile = srcdir "/etc/group" 181 if (system("test -f '" idfile "'") != 0) { 182 print "ERROR: can't find group file '" idfile "'" > "/dev/stderr" 183 exit 1 184 } 185 oldFS=FS 186 FS=":" 187 while (getline < idfile) { 188 gid[$1] = $3 189 } 190 close(idfile) 191 FS=oldFS 192 193 # initially no substitutions 194 devsubst = 0 195 deventry = "" 196} 197 198/%MI_DEVICES_BEGIN%/ { 199 devsubst = 1; 200 next 201} 202 203/%MI_DEVICES_END%/ { 204 devsubst = 0; 205 next 206} 207 208# output 'Generated from' lines 209/\$[N]etBSD/ { 210 print "#" 211 print "# Generated from:" 212 213 # MAKEDEV.awk (this script) RCS Id 214 ARCSID = "$NetBSD: MAKEDEV.awk,v 1.21 2010/03/30 07:30:03 mrg Exp $" 215 gsub(/\$/, "", ARCSID) 216 print "# " ARCSID 217 218 # MAKEDEV.tmpl RCS Id 219 gsub(/\$/, "") 220 print $0 221 222 # MD MAKEDEV.conf RCS Id 223 # strip leading hash and insert machine subdirectory name 224 gsub(/\$/, "", CONFRCSID) 225 sub(/^\# /, "", CONFRCSID) 226 sub(/MAKEDEV.conf/, "etc." machine "/MAKEDEV.conf", CONFRCSID) 227 print "# " CONFRCSID 228 229 next # don't print the RCS Id line again 230} 231 232# filter the 'PLEASE RUN ...' paragraph 233/^\# PLEASE RUN/, /^\#\#\#\#\#\#/ { 234 next 235} 236 237# filter the device list 238/^\# Tapes/,/^$/ { 239 next 240} 241 242# filter the two unneeded makedisk_p* routines, leave only 243# the one used 244/^makedisk_p8\(\) \{/, /^\}/ { 245 if (MKDISK != "makedisk_p8") 246 next; 247} 248/^makedisk_p16\(\) \{/, /^\}/ { 249 if (MKDISK != "makedisk_p16") 250 next; 251} 252/^makedisk_p16high\(\) \{/, /^\}/ { 253 if (MKDISK != "makedisk_p16high") 254 next; 255} 256 257# special cases aside, handle normal line 258{ 259 sub(/^%MD_DEVICES%/, MDDEV) 260 sub(/%MKDISK%/, MKDISK) 261 sub(/%DISKMINOROFFSET%/, DISKMINOROFFSET) 262 sub(/%RAWDISK_OFF%/, RAWDISK_OFF) 263 sub(/%RAWDISK_NAME%/, RAWDISK_NAME) 264 sub(/%CONSOLE_CMAJOR%/, CONSOLE_CMAJOR) 265 parsed = "" 266 line = $0 267 while (match(line, /%[gu]id_[a-z]*%/)) { 268 typ = substr(line, RSTART + 1, 3); 269 nam = substr(line, RSTART + 5, RLENGTH - 6); 270 if (typ == "uid") { 271 if (!(nam in uid)) { 272 print "ERROR unmatched uid in `" $0 "'" > \ 273 "/dev/stderr" 274 exit 1 275 } else 276 id = uid[nam]; 277 } else { 278 if (!(nam in gid)) { 279 print "ERROR unmatched gid in `" $0 "'" > \ 280 "/dev/stderr" 281 exit 1 282 } else 283 id = gid[nam]; 284 } 285 parsed = parsed substr(line, 1, RSTART - 1) id 286 line = substr(line, RSTART + RLENGTH) 287 } 288 $0 = parsed line 289 290 # if device substitutions are not active, do nothing more 291 if (!devsubst) { 292 print 293 next 294 } 295} 296 297# first line of device entry 298/^[a-z].*\)$/ { 299 if (length(deventry) > 0) { 300 # We have a previous entry to print. Replace all known 301 # character and block devices. If no unknown character 302 # or block device definition remains within the entry, 303 # print it to output, otherwise scrap it. 304 parsed = "" 305 while (match(deventry, /%[a-z]*_(blk|chr)%/)) { 306 nam = substr(deventry, RSTART + 1, RLENGTH - 6); 307 typ = substr(deventry, RSTART + RLENGTH - 4, 3); 308 if (typ == "blk") { 309 if (!(nam in blk)) { 310 deventry = $0 311 next 312 } else 313 dev = blk[nam]; 314 } else { 315 if (!(nam in chr)) { 316 deventry = $0 317 next 318 } else 319 dev = chr[nam]; 320 } 321 parsed = parsed substr(deventry, 1, RSTART - 1) dev 322 deventry = substr(deventry, RSTART + RLENGTH) 323 } 324 325 print parsed deventry 326 } 327 deventry = $0 328 next 329} 330 331# template line within device substitution section - just keep appending 332# to the current entry 333{ 334 deventry = deventry "\n" $0 335} 336