1#!/usr/bin/awk - 2# 3# $NetBSD: MAKEDEV.awk,v 1.29 2020/06/13 19:46:23 thorpej 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 ((index(maarch, "arm") != 0 || index(maarch, "aarch64")) && 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 nm = 2; 67 68 # process all files with majors and fill the chr[] and blk[] 69 # arrays, used in template processing 70 for (m = 0; m < nm; m++) { 71 file = top majors[m] 72 if (system("test -f '" file "'") != 0) { 73 print "ERROR: can't find majors file '" file "'" > "/dev/stderr" 74 exit 1 75 } 76 while (getline < file) { 77 if ($1 == "include") { 78 majors[nm++] = substr($2, 2, length($2)-2); 79 } else if ($1 == "device-major") { 80 if ($3 == "char") { 81 chr[$2] = $4 82 if ($5 == "block") 83 blk[$2] = $6 84 } else if ($3 == "block") 85 blk[$2] = $4 86 } 87 } 88 close(file) 89 } 90 CONSOLE_CMAJOR = chr["cons"] 91 if (CONSOLE_CMAJOR == "") { 92 print "ERROR: no entry for 'cons' in majors file" > "/dev/stderr" 93 exit 1 94 } 95 96 # read MD config file for MD device targets 97 cfgfile = srcdir "/etc/etc." machine "/MAKEDEV.conf" 98 if (system("test -f '" cfgfile "'") != 0) { 99 print "ERROR: no platform MAKEDEV.conf - '" cfgfile "' doesn't exist" > "/dev/stderr" 100 exit 1 101 } 102 # skip first two lines 103 getline CONFRCSID < cfgfile # RCS Id 104 getline < cfgfile # blank line 105 MDDEV = 0 # MD device targets 106 while (getline < cfgfile) { 107 # 108 # Perform the same blk / chr subsitution that happens below. 109 # 110 md_deventry = $0 111 if (match(md_deventry, /%[a-z0-9]*_(blk|chr)%/)) { 112 nam = substr(md_deventry, RSTART + 1, RLENGTH - 6); 113 typ = substr(md_deventry, RSTART + RLENGTH - 4, 3); 114 dev = "" 115 if (typ == "blk") { 116 if (nam in blk) { 117 dev = blk[nam]; 118 } 119 } else { 120 if (nam in chr) { 121 dev = chr[nam]; 122 } 123 } 124 if (dev != "") { 125 parsed = substr(md_deventry, 1, RSTART - 1) dev 126 md_deventry = substr(md_deventry, RSTART + RLENGTH) 127 } 128 md_deventry = parsed md_deventry 129 } 130 if (MDDEV) 131 MDDEV = MDDEV "\n" md_deventry 132 else 133 MDDEV = md_deventry 134 } 135 close(cfgfile) 136 137 # determine number of partitions used by platform 138 # there are three variants in tree: 139 # 1. MAXPARTITIONS = 8 140 # 2. MAXPARTITIONS = 16 with no back compat mapping 141 # 3. MAXPARTITIONS = 16 with back compat with old limit of 8 142 # currently all archs, which moved from 8->16 use same 143 # scheme for mapping disk minors, high minor offset 144 # if this changes, the below needs to be adjusted and 145 # additional makedisk_p16foo needs to be added 146 incdir = machine 147 diskpartitions = 0 148 diskbackcompat = 0 149 while (1) { 150 inc = top "arch/" incdir "/include/disklabel.h" 151 if (system("test -f '" inc "'") != 0) { 152 print "ERROR: can't find kernel include file '" inc "'" > "/dev/stderr" 153 exit 1 154 } 155 incdir = 0 156 while (getline < inc) { 157 if ($1 == "#define" && $2 == "MAXPARTITIONS") 158 diskpartitions = $3 159 else if ($1 == "#define" && $2 == "OLDMAXPARTITIONS") 160 diskbackcompat = $3 161 else if ($1 == "#ifndef" && $2 == "RAW_PART" && 162 RAWDISK_OFF) { 163 # special case to ignore #ifndef RAW_PART 164 # sections (e.g. in arm/include/disklabel.h, 165 # when it is already set in 166 # zaurus/include/disklabel.h) 167 while (getline < inc) { 168 # skip all lines upto the next #endif 169 if ($1 == "#endif") 170 break; 171 } 172 } else if ($1 == "#define" && $2 == "RAW_PART") 173 RAWDISK_OFF = $3 174 else if ($1 == "#include" && 175 $2 ~ "<.*/disklabel.h>" && 176 $2 !~ ".*nbinclude.*") 177 { 178 # wrapper, switch to the right file 179 incdir = substr($2, 2) 180 sub("/.*", "", incdir) 181 break; 182 } 183 } 184 close(inc) 185 186 if (diskpartitions) 187 break; 188 189 if (!incdir) { 190 print "ERROR: can't determine MAXPARTITIONS from include file '" inc "'" > "/dev/stderr" 191 exit 1 192 } 193 } 194 MKDISK = "makedisk_p" diskpartitions # routine to create disk devs 195 DISKMINOROFFSET = diskpartitions 196 if (diskbackcompat) { 197 MKDISK = MKDISK "high" 198 DISKMINOROFFSET = diskbackcompat 199 } 200 RAWDISK_NAME = sprintf("%c", 97 + RAWDISK_OFF) # a+offset 201 202 # read etc/master.passwd for user name->UID mapping 203 idfile = srcdir "/etc/master.passwd" 204 if (system("test -f '" idfile "'") != 0) { 205 print "ERROR: can't find password file '" idfile "'" > "/dev/stderr" 206 exit 1 207 } 208 oldFS=FS 209 FS=":" 210 while (getline < idfile) { 211 uid[$1] = $3 212 } 213 close(idfile) 214 FS=oldFS 215 216 # read etc/group for group name->GID mapping 217 idfile = srcdir "/etc/group" 218 if (system("test -f '" idfile "'") != 0) { 219 print "ERROR: can't find group file '" idfile "'" > "/dev/stderr" 220 exit 1 221 } 222 oldFS=FS 223 FS=":" 224 while (getline < idfile) { 225 gid[$1] = $3 226 } 227 close(idfile) 228 FS=oldFS 229 230 # initially no substitutions 231 devsubst = 0 232 deventry = "" 233} 234 235/%MI_DEVICES_BEGIN%/ { 236 devsubst = 1; 237 next 238} 239 240/%MI_DEVICES_END%/ { 241 devsubst = 0; 242 next 243} 244 245# output 'Generated from' lines 246/\$[N]etBSD/ { 247 print "#" 248 print "# Generated from:" 249 250 # MAKEDEV.awk (this script) RCS Id 251 ARCSID = "$NetBSD: MAKEDEV.awk,v 1.29 2020/06/13 19:46:23 thorpej Exp $" 252 gsub(/\$/, "", ARCSID) 253 print "# " ARCSID 254 255 # MAKEDEV.tmpl RCS Id 256 gsub(/\$/, "") 257 print $0 258 259 # MD MAKEDEV.conf RCS Id 260 # strip leading hash and insert machine subdirectory name 261 gsub(/\$/, "", CONFRCSID) 262 sub(/^\# /, "", CONFRCSID) 263 sub(/MAKEDEV.conf/, "etc." machine "/MAKEDEV.conf", CONFRCSID) 264 print "# " CONFRCSID 265 266 next # don't print the RCS Id line again 267} 268 269# filter the 'PLEASE RUN ...' paragraph 270/^\# PLEASE RUN/, /^\#\#\#\#\#\#/ { 271 next 272} 273 274# filter the device list 275/^\# Tapes/,/^$/ { 276 next 277} 278 279# filter the two unneeded makedisk_p* routines, leave only 280# the one used 281/^makedisk_p8\(\) \{/, /^\}/ { 282 if (MKDISK != "makedisk_p8") 283 next; 284} 285/^makedisk_p16\(\) \{/, /^\}/ { 286 if (MKDISK != "makedisk_p16") 287 next; 288} 289/^makedisk_p16high\(\) \{/, /^\}/ { 290 if (MKDISK != "makedisk_p16high") 291 next; 292} 293 294# special cases aside, handle normal line 295{ 296 sub(/^%MD_DEVICES%/, MDDEV) 297 sub(/%MKDISK%/, MKDISK) 298 sub(/%DISKMINOROFFSET%/, DISKMINOROFFSET) 299 sub(/%RAWDISK_OFF%/, RAWDISK_OFF) 300 sub(/%RAWDISK_NAME%/, RAWDISK_NAME) 301 sub(/%CONSOLE_CMAJOR%/, CONSOLE_CMAJOR) 302 parsed = "" 303 line = $0 304 while (match(line, /%[gu]id_[_a-z]*%/)) { 305 typ = substr(line, RSTART + 1, 3); 306 nam = substr(line, RSTART + 5, RLENGTH - 6); 307 if (typ == "uid") { 308 if (!(nam in uid)) { 309 print "ERROR unmatched uid in `" $0 "'" > \ 310 "/dev/stderr" 311 exit 1 312 } else 313 id = uid[nam]; 314 } else { 315 if (!(nam in gid)) { 316 print "ERROR unmatched gid in `" $0 "'" > \ 317 "/dev/stderr" 318 exit 1 319 } else 320 id = gid[nam]; 321 } 322 parsed = parsed substr(line, 1, RSTART - 1) id 323 line = substr(line, RSTART + RLENGTH) 324 } 325 $0 = parsed line 326 327 # if device substitutions are not active, do nothing more 328 if (!devsubst) { 329 print 330 next 331 } 332} 333 334# first line of device entry 335/^[a-z].*\)$/ { 336 if (length(deventry) > 0) { 337 # We have a previous entry to print. Replace all known 338 # character and block devices. If no unknown character 339 # or block device definition remains within the entry, 340 # print it to output, otherwise scrap it. 341 parsed = "" 342 while (match(deventry, /%[a-z0-9]*_(blk|chr)%/)) { 343 nam = substr(deventry, RSTART + 1, RLENGTH - 6); 344 typ = substr(deventry, RSTART + RLENGTH - 4, 3); 345 if (typ == "blk") { 346 if (!(nam in blk)) { 347 deventry = $0 348 next 349 } else 350 dev = blk[nam]; 351 } else { 352 if (!(nam in chr)) { 353 deventry = $0 354 next 355 } else 356 dev = chr[nam]; 357 } 358 parsed = parsed substr(deventry, 1, RSTART - 1) dev 359 deventry = substr(deventry, RSTART + RLENGTH) 360 } 361 362 print parsed deventry 363 } 364 deventry = $0 365 next 366} 367 368# template line within device substitution section - just keep appending 369# to the current entry 370{ 371 deventry = deventry "\n" $0 372} 373