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