Index: head/tools/build/mk/Makefile.boot =================================================================== --- head/tools/build/mk/Makefile.boot (revision 298880) +++ head/tools/build/mk/Makefile.boot (revision 298881) @@ -1,9 +1,9 @@ # $FreeBSD$ CFLAGS+= -I${WORLDTMP}/legacy/usr/include DPADD+= ${WORLDTMP}/legacy/usr/lib/libegacy.a LDADD+= -legacy LDFLAGS+= -L${WORLDTMP}/legacy/usr/lib -# we do not want to capture dependencies refering to the above +# we do not want to capture dependencies referring to the above UPDATE_DEPENDFILE= no Index: head/tools/regression/sockets/so_setfib/so_setfib.c =================================================================== --- head/tools/regression/sockets/so_setfib/so_setfib.c (revision 298880) +++ head/tools/regression/sockets/so_setfib/so_setfib.c (revision 298881) @@ -1,200 +1,200 @@ /*- * Copyright (c) 2012 Cisco Systems, Inc. * All rights reserved. * * This software was developed by Bjoern Zeeb under contract to * Cisco Systems, Inc.. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Regression test on SO_SETFIB setsockopt(2). * * Check that the expected domain(9) families all handle the socket option * correctly and do proper bounds checks. * * Test plan: * 1. Get system wide number of FIBs from sysctl and convert to index (-= 1). * 2. For each protocol family (INET, INET6, ROUTE and LOCAL) open socketes of * type (STREAM, DGRAM and RAW) as supported. * 3. Do a sequence of -2, -1, 0, .. n, n+1, n+2 SO_SETFIB sockopt calls, * expecting the first two and last two to fail (valid 0 ... n). * 4. Try 3 random numbers. Calculate result based on valid range. * 5. Repeat for next domain family and type from (2) on. */ #include #include #include #include #include #include #include #include #include #include static struct t_dom { int domain; const char *name; } t_dom[] = { #ifdef INET6 { .domain = PF_INET6, .name = "PF_INET6" }, #endif #ifdef INET { .domain = PF_INET, .name = "PF_INET" }, #endif { .domain = PF_ROUTE, .name = "PF_ROUTE" }, { .domain = PF_LOCAL, .name = "PF_LOCAL" }, }; static struct t_type { int type; const char *name; } t_type[] = { { .type = SOCK_STREAM, .name = "SOCK_STREAM" }, { .type = SOCK_DGRAM, .name = "SOCK_DGRAM" }, { .type = SOCK_RAW, .name = "SOCK_RAW" }, }; /* * Number of FIBs as read from net.fibs sysctl - 1. Initialize to clear out of * bounds value to not accidentally run on a limited range. */ static int rt_numfibs = -42; /* Number of test case. */ static int testno = 1; /* * Try the setsockopt with given FIB number i on socket s. * Handle result given on error and valid range and errno. */ static void so_setfib(int s, int i, u_int dom, u_int type) { int error; error = setsockopt(s, SOL_SOCKET, SO_SETFIB, &i, sizeof(i)); /* For out of bounds we expect an error. */ if (error == -1 && (i < 0 || i > rt_numfibs)) printf("ok %d %s_%s_%d\n", testno, t_dom[dom].name, t_type[type].name, i); else if (error != -1 && (i < 0 || i > rt_numfibs)) printf("not ok %d %s_%s_%d # setsockopt(%d, SOL_SOCKET, " "SO_SETFIB, %d, ..) unexpectedly succeeded\n", testno, t_dom[dom].name, t_type[type].name, i, s, i); else if (error == 0) printf("ok %d %s_%s_%d\n", testno, t_dom[dom].name, t_type[type].name, i); else if (errno != EINVAL) printf("not ok %d %s_%s_%d # setsockopt(%d, SOL_SOCKET, " "SO_SETFIB, %d, ..) unexpected error: %s\n", testno, t_dom[dom].name, t_type[type].name, i, s, i, strerror(errno)); else printf("not ok %d %s_%s_%d\n", testno, t_dom[dom].name, t_type[type].name, i); /* Test run done, next please. */ testno++; } /* * Main test. Open socket given domain family and type. For each FIB, out of * bounds FIB numbers and 3 random FIB numbers set the socket option. */ static void t(u_int dom, u_int type) { int i, s; /* PF_ROUTE only supports RAW socket types, while PF_LOCAL does not. */ if (t_dom[dom].domain == PF_ROUTE && t_type[type].type != SOCK_RAW) return; if (t_dom[dom].domain == PF_LOCAL && t_type[type].type == SOCK_RAW) return; /* Open socket for given combination. */ s = socket(t_dom[dom].domain, t_type[type].type, 0); if (s == -1) { printf("not ok %d %s_%s # socket(): %s\n", testno, t_dom[dom].name, t_type[type].name, strerror(errno)); testno++; return; } /* Test FIBs -2, -1, 0, .. n, n + 1, n + 2. */ for (i = -2; i <= (rt_numfibs + 2); i++) so_setfib(s, i, dom, type); /* Test 3 random FIB numbers. */ for (i = 0; i < 3; i++) so_setfib(s, (int)random(), dom, type); /* Close socket. */ close(s); } /* * Returns 0 if no program error, 1 on sysctlbyname error. * Test results are communicated by printf("[not ]ok .."). */ int main(int argc __unused, char *argv[] __unused) { u_int i, j; size_t s; if (geteuid() != 0) { printf("1..0 # SKIP: must be root\n"); return (0); } - /* Initalize randomness. */ + /* Initialize randomness. */ srandomdev(); /* Get number of FIBs supported by kernel. */ s = sizeof(rt_numfibs); if (sysctlbyname("net.fibs", &rt_numfibs, &s, NULL, 0) == -1) err(1, "sysctlbyname(net.fibs, ..)"); printf("1..%lu\n", (nitems(t_dom) - 1) * nitems(t_type) * (2 + rt_numfibs + 2 + 3)); /* Adjust from number to index. */ rt_numfibs -= 1; /* Run tests. */ for (i = 0; i < sizeof(t_dom) / sizeof(struct t_dom); i++) for (j = 0; j < sizeof(t_type) / sizeof(struct t_type); j++) t(i, j); return (0); } /* end */ Index: head/tools/tools/fixwhite/fixwhite.1 =================================================================== --- head/tools/tools/fixwhite/fixwhite.1 (revision 298880) +++ head/tools/tools/fixwhite/fixwhite.1 (revision 298881) @@ -1,48 +1,48 @@ .\" Copyright (c) 2012 Ed Schouten .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd February 6, 2012 .Dt FIXWHITE 1 .Os .Sh NAME .Nm fixwhite .Nd remove unneeded whitespace from text files .Sh SYNOPSIS .Nm .Sh DESCRIPTION The .Nm utility removes unneeded whitespace from text passed to standard input and prints the result to standard output. .Pp It removes leading and trailing empty lines from the input, as well as trailing whitespace characters from ever line of text. Multiple successive empty lines are merged together. If the whitespace at the beginning of a sentence is exactly a multiple of eight spaces, the whitespace is replaced by tabs. -Also, spaces preceeding tabs will be merged into the tab character. +Also, spaces preceding tabs will be merged into the tab character. .Sh AUTHORS .An Ed Schouten Aq Mt ed@FreeBSD.org Index: head/tools/tools/fixwhite/fixwhite.c =================================================================== --- head/tools/tools/fixwhite/fixwhite.c (revision 298880) +++ head/tools/tools/fixwhite/fixwhite.c (revision 298881) @@ -1,180 +1,180 @@ /*- * Copyright (c) 2012 Ed Schouten * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include static char *queue = NULL; static size_t queuelen = 0, queuesize = 0; static off_t column = 0; static void savebyte(char c) { if (queuelen >= queuesize) { queuesize += 128; queue = realloc(queue, queuesize); if (queue == NULL) { perror("malloc"); exit(1); } } queue[queuelen++] = c; switch (c) { case '\n': column = 0; break; case ' ': column++; break; case '\t': column = (column / 8 + 1) * 8; break; } } static bool peekbyte(size_t back, char c) { return (queuelen >= back && queue[queuelen - back] == c); } static void savewhite(char c, bool leading) { off_t ncolumn; switch (c) { case '\n': if (leading) { /* Remove empty lines before input. */ queuelen = 0; column = 0; } else { /* Remove trailing whitespace. */ while (peekbyte(1, ' ') || peekbyte(1, '\t')) queuelen--; /* Remove redundant empty lines. */ if (peekbyte(2, '\n') && peekbyte(1, '\n')) return; savebyte('\n'); } break; case ' ': savebyte(' '); break; case '\t': - /* Convert preceeding spaces to tabs. */ + /* Convert preceding spaces to tabs. */ ncolumn = (column / 8 + 1) * 8; while (peekbyte(1, ' ')) { queuelen--; column--; } while (column < ncolumn) savebyte('\t'); break; } } static void printwhite(void) { off_t i; /* Merge spaces at the start of a sentence to tabs if possible. */ if ((column % 8) == 0) { for (i = 0; i < column; i++) if (!peekbyte(i + 1, ' ')) break; if (i == column) { queuelen -= column; for (i = 0; i < column; i += 8) queue[queuelen++] = '\t'; } } if (fwrite(queue, 1, queuelen, stdout) != queuelen) { perror("write"); exit(1); } queuelen = 0; } static char readchar(void) { int c; c = getchar(); if (c == EOF && ferror(stdin)) { perror("read"); exit(1); } return (c); } static void writechar(char c) { if (putchar(c) == EOF) { perror("write"); exit(1); } /* XXX: Multi-byte characters. */ column++; } int main(void) { int c; bool leading = true; while ((c = readchar()) != EOF) { if (isspace(c)) /* Save whitespace. */ savewhite(c, leading); else { /* Reprint whitespace and print regular character. */ printwhite(); writechar(c); leading = false; } } /* Terminate non-empty files with a newline. */ if (!leading) writechar('\n'); return (0); } Index: head/tools/tools/ipw/ipwstats.c =================================================================== --- head/tools/tools/ipw/ipwstats.c (revision 298880) +++ head/tools/tools/ipw/ipwstats.c (revision 298881) @@ -1,277 +1,277 @@ /*- * Copyright (c) 2006 Damien Bergamini * Copyright (c) 2006 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include static void get_statistics(const char *); int main(int argc, char **argv) { get_statistics((argc > 1) ? argv[1] : "ipw0"); return EX_OK; } struct statistic { int index; const char *desc; int unit; #define INT 1 #define HEX 2 #define MASK HEX #define PERCENTAGE 3 #define BOOL 4 }; /*- * TIM = Traffic Information Message * DTIM = Delivery TIM * ATIM = Announcement TIM * PSP = Power Save Poll * RTS = Request To Send * CTS = Clear To Send * RSSI = Received Signal Strength Indicator */ static const struct statistic tbl[] = { { 1, "Number of frames submitted for transfer", INT }, { 2, "Number of frames transmitted", INT }, { 3, "Number of unicast frames transmitted", INT }, { 4, "Number of unicast frames transmitted at 1Mb/s", INT }, { 5, "Number of unicast frames transmitted at 2Mb/s", INT }, { 6, "Number of unicast frames transmitted at 5.5Mb/s", INT }, { 7, "Number of unicast frames transmitted at 11Mb/s", INT }, { 13, "Number of multicast frames transmitted at 1Mb/s", INT }, { 14, "Number of multicast frames transmitted at 2Mb/s", INT }, { 15, "Number of multicast frames transmitted at 5.5Mb/s", INT }, { 16, "Number of multicast frames transmitted at 11Mb/s", INT }, { 21, "Number of null frames transmitted", INT }, { 22, "Number of RTS frames transmitted", INT }, { 23, "Number of CTS frames transmitted", INT }, { 24, "Number of ACK frames transmitted", INT }, { 25, "Number of association requests transmitted", INT }, { 26, "Number of association responses transmitted", INT }, { 27, "Number of reassociation requests transmitted", INT }, { 28, "Number of reassociation responses transmitted", INT }, { 29, "Number of probe requests transmitted", INT }, - { 30, "Number of probe reponses transmitted", INT }, + { 30, "Number of probe responses transmitted", INT }, { 31, "Number of beacons transmitted", INT }, { 32, "Number of ATIM frames transmitted", INT }, { 33, "Number of disassociation requests transmitted", INT }, { 34, "Number of authentication requests transmitted", INT }, { 35, "Number of deauthentication requests transmitted", INT }, { 41, "Number of bytes transmitted", INT }, { 42, "Number of transmission retries", INT }, { 43, "Number of transmission retries at 1Mb/s", INT }, { 44, "Number of transmission retries at 2Mb/s", INT }, { 45, "Number of transmission retries at 5.5Mb/s", INT }, { 46, "Number of transmission retries at 11Mb/s", INT }, { 51, "Number of transmission failures", INT }, { 54, "Number of transmission aborted due to slow DMA setup", INT }, { 56, "Number of disassociation failures", INT }, { 58, "Number of spanning tree frames transmitted", INT }, { 59, "Number of transmission errors due to missing ACK", INT }, { 61, "Number of frames received", INT }, { 62, "Number of unicast frames received", INT }, { 63, "Number of unicast frames received at 1Mb/s", INT }, { 64, "Number of unicast frames received at 2Mb/s", INT }, { 65, "Number of unicast frames received at 5.5Mb/s", INT }, { 66, "Number of unicast frames received at 11Mb/s", INT }, { 71, "Number of multicast frames received", INT }, { 72, "Number of multicast frames received at 1Mb/s", INT }, { 73, "Number of multicast frames received at 2Mb/s", INT }, { 74, "Number of multicast frames received at 5.5Mb/s", INT }, { 75, "Number of multicast frames received at 11Mb/s", INT }, { 80, "Number of null frames received", INT }, { 81, "Number of poll frames received", INT }, { 82, "Number of RTS frames received", INT }, { 83, "Number of CTS frames received", INT }, { 84, "Number of ACK frames received", INT }, { 85, "Number of CF-End frames received", INT }, { 86, "Number of CF-End + CF-Ack frames received", INT }, { 87, "Number of association requests received", INT }, { 88, "Number of association responses received", INT }, { 89, "Number of reassociation requests received", INT }, { 90, "Number of reassociation responses received", INT }, { 91, "Number of probe requests received", INT }, - { 92, "Number of probe reponses received", INT }, + { 92, "Number of probe responses received", INT }, { 93, "Number of beacons received", INT }, { 94, "Number of ATIM frames received", INT }, { 95, "Number of disassociation requests received", INT }, { 96, "Number of authentication requests received", INT }, { 97, "Number of deauthentication requests received", INT }, { 101, "Number of bytes received", INT }, { 102, "Number of frames with a bad CRC received", INT }, { 103, "Number of frames with a bad CRC received at 1Mb/s", INT }, { 104, "Number of frames with a bad CRC received at 2Mb/s", INT }, { 105, "Number of frames with a bad CRC received at 5.5Mb/s", INT }, { 106, "Number of frames with a bad CRC received at 11Mb/s", INT }, { 112, "Number of duplicated frames received at 1Mb/s", INT }, { 113, "Number of duplicated frames received at 2Mb/s", INT }, { 114, "Number of duplicated frames received at 5.5Mb/s", INT }, { 115, "Number of duplicated frames received at 11Mb/s", INT }, { 119, "Number of duplicated frames received", INT }, { 123, "Number of frames with a bad protocol received", INT }, { 124, "Boot time", INT }, { 125, "Number of frames dropped due to no buffer", INT }, { 126, "Number of frames dropped due to slow DMA setup", INT }, { 128, "Number of frames dropped due to missing fragment", INT }, { 129, "Number of frames dropped due to non-seq fragment", INT }, { 130, "Number of frames dropped due to missing first frame", INT }, { 131, "Number of frames dropped due to incomplete frame", INT }, { 137, "Number of PSP adapter suspends", INT }, { 138, "Number of PSP beacon timeouts", INT }, { 139, "Number of PSP PsPollResponse timeouts", INT }, { 140, "Number of PSP mcast frame timeouts", INT }, { 141, "Number of PSP DTIM frames received", INT }, { 142, "Number of PSP TIM frames received", INT }, { 143, "PSP station Id", INT }, { 147, "RTC time of last association", INT }, { 148, "Percentage of missed beacons", PERCENTAGE }, { 149, "Percentage of missed transmission retries", PERCENTAGE }, { 151, "Number of access points in access points table", INT }, { 153, "Number of associations", INT }, { 154, "Number of association failures", INT }, { 156, "Number of full scans", INT }, { 157, "Card disabled", BOOL }, { 160, "RSSI at time of association", INT }, { 161, "Number of reassociations due to no probe response", INT }, { 162, "Number of reassociations due to poor line quality", INT }, { 163, "Number of reassociations due to load", INT }, { 164, "Number of reassociations due to access point RSSI level", INT }, { 165, "Number of reassociations due to load leveling", INT }, { 170, "Number of times authentication failed", INT }, { 171, "Number of times authentication response failed", INT }, { 172, "Number of entries in association table", INT }, { 173, "Average RSSI", INT }, { 176, "Self test status", INT }, { 177, "Power mode", INT }, { 178, "Power index", INT }, { 179, "IEEE country code", HEX }, { 180, "Channels supported for this country", MASK }, { 181, "Number of adapter warm resets", INT }, { 182, "Beacon interval", INT }, { 184, "Princeton version", INT }, { 185, "Antenna diversity disabled", BOOL }, #if notset { 186, "CCA RSSI", INT }, { 187, "Number of times EEPROM updated", INT }, #endif { 188, "Beacon intervals between DTIM", INT }, { 189, "Current channel", INT }, { 190, "RTC time", INT }, { 191, "Operating mode", INT }, { 192, "Transmission rate", HEX }, { 193, "Supported transmission rates", MASK }, { 194, "ATIM window", INT }, { 195, "Supported basic transmission rates", MASK }, { 196, "Adapter highest rate", HEX }, { 197, "Access point highest rate", HEX }, { 198, "Management frame capability", BOOL }, { 199, "Type of authentication", INT }, { 200, "Adapter card platform type", INT }, { 201, "RTS threshold", INT }, { 202, "International mode", BOOL }, { 203, "Fragmentation threshold", INT }, { 209, "MAC version", INT }, { 210, "MAC revision", INT }, { 211, "Radio version", INT }, { 212, "NIC manufacturing date+time", INT }, { 213, "Microcode version", INT }, { 214, "RF switch state", INT }, { 0, NULL, 0 } }; static void get_statistics(const char *iface) { static uint32_t stats[256]; const struct statistic *stat; char oid[32]; int ifaceno, len; if (sscanf(iface, "ipw%u", &ifaceno) != 1) errx(EX_DATAERR, "Invalid interface name '%s'", iface); len = sizeof stats; snprintf(oid, sizeof oid, "dev.ipw.%u.stats", ifaceno); if (sysctlbyname(oid, stats, &len, NULL, 0) == -1) err(EX_OSERR, "Can't retrieve statistics"); for (stat = tbl; stat->index != 0; stat++) { printf("%-60s[", stat->desc); switch (stat->unit) { case INT: printf("%u", stats[stat->index]); break; case BOOL: printf(stats[stat->index] ? "true" : "false"); break; case PERCENTAGE: printf("%u%%", stats[stat->index]); break; case HEX: default: printf("0x%08X", stats[stat->index]); } printf("]\n"); } } Index: head/tools/tools/nanobsd/defaults.sh =================================================================== --- head/tools/tools/nanobsd/defaults.sh (revision 298880) +++ head/tools/tools/nanobsd/defaults.sh (revision 298881) @@ -1,1102 +1,1102 @@ #!/bin/sh # # Copyright (c) 2005 Poul-Henning Kamp. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # set -e ####################################################################### # # Setup default values for all controlling variables. # These values can be overridden from the config file(s) # ####################################################################### # Name of this NanoBSD build. (Used to construct workdir names) NANO_NAME=full # Source tree directory NANO_SRC=/usr/src # Where nanobsd additional files live under the source tree NANO_TOOLS=tools/tools/nanobsd # Where cust_pkgng() finds packages to install NANO_PACKAGE_DIR=${NANO_SRC}/${NANO_TOOLS}/Pkg NANO_PACKAGE_LIST="*" # where package metadata gets placed NANO_PKG_META_BASE=/var/db # Path to mtree file to apply to anything copied by cust_install_files(). # If you specify this, the mtree file *must* have an entry for every file and # directory located in Files. #NANO_CUST_FILES_MTREE="" # Object tree directory # default is subdir of /usr/obj #NANO_OBJ="" # The directory to put the final images # default is ${NANO_OBJ} #NANO_DISKIMGDIR="" # Make & parallel Make NANO_MAKE="make" NANO_PMAKE="make -j 3" # The default name for any image we create. NANO_IMGNAME="_.disk.full" # Options to put in make.conf during buildworld only CONF_BUILD=' ' # Options to put in make.conf during installworld only CONF_INSTALL=' ' # Options to put in make.conf during both build- & installworld. CONF_WORLD=' ' # Kernel config file to use NANO_KERNEL=GENERIC # Kernel modules to install. If empty, no modules are installed. # Use "default" to install all built modules. NANO_MODULES= # Early customize commands. NANO_EARLY_CUSTOMIZE="" # Customize commands. NANO_CUSTOMIZE="" # Late customize commands. NANO_LATE_CUSTOMIZE="" -# Newfs paramters to use +# Newfs parameters to use NANO_NEWFS="-b 4096 -f 512 -i 8192 -U" # The drive name of the media at runtime NANO_DRIVE=ada0 # Target media size in 512 bytes sectors NANO_MEDIASIZE=2000000 # Number of code images on media (1 or 2) NANO_IMAGES=2 # 0 -> Leave second image all zeroes so it compresses better. # 1 -> Initialize second image with a copy of the first NANO_INIT_IMG2=1 # Size of code file system in 512 bytes sectors # If zero, size will be as large as possible. NANO_CODESIZE=0 # Size of configuration file system in 512 bytes sectors # Cannot be zero. NANO_CONFSIZE=2048 # Size of data file system in 512 bytes sectors # If zero: no partition configured. # If negative: max size possible NANO_DATASIZE=0 # Size of the /etc ramdisk in 512 bytes sectors NANO_RAM_ETCSIZE=10240 # Size of the /tmp+/var ramdisk in 512 bytes sectors NANO_RAM_TMPVARSIZE=10240 # Media geometry, only relevant if bios doesn't understand LBA. NANO_SECTS=63 NANO_HEADS=16 # boot0 flags/options and configuration NANO_BOOT0CFG="-o packet -s 1 -m 3" NANO_BOOTLOADER="boot/boot0sio" # boot2 flags/options # default force serial console NANO_BOOT2CFG="-h -S115200" # Backing type of md(4) device # Can be "file" or "swap" NANO_MD_BACKING="file" # for swap type md(4) backing, write out the mbr only NANO_IMAGE_MBRONLY=true # Progress Print level PPLEVEL=3 # Set NANO_LABEL to non-blank to form the basis for using /dev/ufs/label # in preference to /dev/${NANO_DRIVE} # Root partition will be ${NANO_LABEL}s{1,2} # /cfg partition will be ${NANO_LABEL}s3 # /data partition will be ${NANO_LABEL}s4 NANO_LABEL="" NANO_SLICE_ROOT=s1 NANO_SLICE_ALTROOT=s2 NANO_SLICE_CFG=s3 NANO_SLICE_DATA=s4 NANO_ROOT=s1a NANO_ALTROOT=s2a # Default ownwership for nopriv build NANO_DEF_UNAME=root NANO_DEF_GNAME=wheel ####################################################################### # Architecture to build. Corresponds to TARGET_ARCH in a buildworld. # Unfortunately, there's no way to set TARGET at this time, and it # conflates the two, so architectures where TARGET != TARGET_ARCH and # TARGET can't be guessed from TARGET_ARCH do not work. This defaults # to the arch of the current machine. NANO_ARCH=`uname -p` # CPUTYPE defaults to "" which is the default when CPUTYPE isn't # defined. NANO_CPUTYPE="" # Directory to populate /cfg from NANO_CFGDIR="" # Directory to populate /data from NANO_DATADIR="" # We don't need SRCCONF or SRC_ENV_CONF. NanoBSD puts everything we # need for the build in files included with __MAKE_CONF. Override in your # config file if you really must. We set them unconditionally here, though # in case they are stray in the build environment SRCCONF=/dev/null SRC_ENV_CONF=/dev/null ####################################################################### # # The functions which do the real work. # Can be overridden from the config file(s) # ####################################################################### # Export values into the shell. Must use { } instead of ( ) like # other functions to avoid a subshell. # We set __MAKE_CONF as a global since it is easier to get quoting # right for paths with spaces in them. make_export ( ) { # Similar to export_var, except puts the data out to stdout var=$1 eval val=\$$var echo "Setting variable: $var=\"$val\"" export $1 } nano_make_build_env ( ) { __MAKE_CONF="${NANO_MAKE_CONF_BUILD}" make_export __MAKE_CONF } nano_make_install_env ( ) { __MAKE_CONF="${NANO_MAKE_CONF_INSTALL}" make_export __MAKE_CONF } # Extra environment variables for kernel builds nano_make_kernel_env ( ) { if [ -f ${NANO_KERNEL} ] ; then KERNCONFDIR="$(realpath $(dirname ${NANO_KERNEL}))" KERNCONF="$(basename ${NANO_KERNEL})" make_export KERNCONFDIR make_export KERNCONF else export KERNCONF="${NANO_KERNEL}" make_export KERNCONF fi } nano_global_make_env ( ) ( # global settings for the make.conf file, if set [ -z "${NANO_ARCH}" ] || echo TARGET_ARCH="${NANO_ARCH}" [ -z "${NANO_CPUTYPE}" ] || echo TARGET_CPUTYPE="${NANO_CPUTYPE}" ) # rm doesn't know -x prior to FreeBSD 10, so cope with a variety of build # hosts for now. This will go away when support in the base goes away. rm ( ) { echo "NANO RM $*" case $(uname -r) in 7*|8*|9*) command rm $* ;; *) command rm -x $* ;; esac } # # Create empty files in the target tree, and record the fact. All paths # are relative to NANO_WORLDDIR. # tgt_touch ( ) ( cd "${NANO_WORLDDIR}" for i; do touch $i echo "./${i} type=file" >> ${NANO_METALOG} done ) # # Convert a directory into a symlink. Takes two arguments, the # current directory and what it should become a symlink to. The # directory is removed and a symlink is created. If we're doing # a nopriv build, then append this fact to the metalog # tgt_dir2symlink () ( dir=$1 symlink=$2 cd "${NANO_WORLDDIR}" rm -rf "$dir" ln -s "$symlink" "$dir" if [ -n "$NANO_METALOG" ]; then echo "./${dir} type=link mode=0777 link=${symlink}" >> ${NANO_METALOG} fi ) # run in the world chroot, errors fatal CR ( ) { chroot "${NANO_WORLDDIR}" /bin/sh -exc "$*" } # run in the world chroot, errors not fatal CR0 ( ) { chroot "${NANO_WORLDDIR}" /bin/sh -c "$*" || true } nano_cleanup ( ) ( [ $? -eq 0 ] || echo "Error encountered. Check for errors in last log file." 1>&2 exit $? ) clean_build ( ) ( pprint 2 "Clean and create object directory (${MAKEOBJDIRPREFIX})" if ! rm -rf ${MAKEOBJDIRPREFIX}/ > /dev/null 2>&1 ; then chflags -R noschg ${MAKEOBJDIRPREFIX}/ rm -r ${MAKEOBJDIRPREFIX}/ fi ) make_conf_build ( ) ( pprint 2 "Construct build make.conf ($NANO_MAKE_CONF_BUILD)" mkdir -p ${MAKEOBJDIRPREFIX} printenv > ${MAKEOBJDIRPREFIX}/_.env # Make sure we get all the global settings that NanoBSD wants # in addition to the user's global settings ( nano_global_make_env echo "${CONF_WORLD}" echo "${CONF_BUILD}" ) > ${NANO_MAKE_CONF_BUILD} ) build_world ( ) ( pprint 2 "run buildworld" pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bw" ( nano_make_build_env set -o xtrace cd "${NANO_SRC}" ${NANO_PMAKE} buildworld ) > ${MAKEOBJDIRPREFIX}/_.bw 2>&1 ) build_kernel ( ) ( local extra pprint 2 "build kernel ($NANO_KERNEL)" pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bk" ( nano_make_build_env nano_make_kernel_env # Note: We intentionally build all modules, not only the ones in # NANO_MODULES so the built world can be reused by multiple images. - # Although MODULES_OVERRIDE can be defined in the kenrel config + # Although MODULES_OVERRIDE can be defined in the kernel config # file to override this behavior. Just set NANO_MODULES=default. set -o xtrace cd "${NANO_SRC}" ${NANO_PMAKE} buildkernel ) > ${MAKEOBJDIRPREFIX}/_.bk 2>&1 ) clean_world ( ) ( if [ "${NANO_OBJ}" != "${MAKEOBJDIRPREFIX}" ]; then pprint 2 "Clean and create object directory (${NANO_OBJ})" if ! rm -rf ${NANO_OBJ}/ > /dev/null 2>&1 ; then chflags -R noschg ${NANO_OBJ} rm -r ${NANO_OBJ}/ fi mkdir -p "${NANO_OBJ}" "${NANO_WORLDDIR}" printenv > ${NANO_LOG}/_.env else pprint 2 "Clean and create world directory (${NANO_WORLDDIR})" if ! rm -rf "${NANO_WORLDDIR}/" > /dev/null 2>&1 ; then chflags -R noschg "${NANO_WORLDDIR}" rm -rf "${NANO_WORLDDIR}/" fi mkdir -p "${NANO_WORLDDIR}" fi ) make_conf_install ( ) ( pprint 2 "Construct install make.conf ($NANO_MAKE_CONF_INSTALL)" # Make sure we get all the global settings that NanoBSD wants # in addition to the user's global settings ( nano_global_make_env echo "${CONF_WORLD}" echo "${CONF_INSTALL}" if [ -n "${NANO_NOPRIV_BUILD}" ]; then echo NO_ROOT=t echo METALOG=${NANO_METALOG} fi ) > ${NANO_MAKE_CONF_INSTALL} ) install_world ( ) ( pprint 2 "installworld" pprint 3 "log: ${NANO_LOG}/_.iw" ( nano_make_install_env set -o xtrace cd "${NANO_SRC}" ${NANO_MAKE} installworld DESTDIR="${NANO_WORLDDIR}" chflags -R noschg "${NANO_WORLDDIR}" ) > ${NANO_LOG}/_.iw 2>&1 ) install_etc ( ) ( pprint 2 "install /etc" pprint 3 "log: ${NANO_LOG}/_.etc" ( nano_make_install_env set -o xtrace cd "${NANO_SRC}" ${NANO_MAKE} distribution DESTDIR="${NANO_WORLDDIR}" # make.conf doesn't get created by default, but some ports need it # so they can spam it. cp /dev/null "${NANO_WORLDDIR}"/etc/make.conf ) > ${NANO_LOG}/_.etc 2>&1 ) install_kernel ( ) ( local extra pprint 2 "install kernel ($NANO_KERNEL)" pprint 3 "log: ${NANO_LOG}/_.ik" ( nano_make_install_env nano_make_kernel_env if [ "${NANO_MODULES}" != "default" ]; then MODULES_OVERRIDE="${NANO_MODULES}" make_export MODULES_OVERRIDE fi set -o xtrace cd "${NANO_SRC}" ${NANO_MAKE} installkernel DESTDIR="${NANO_WORLDDIR}" ) > ${NANO_LOG}/_.ik 2>&1 ) native_xtools ( ) ( print 2 "Installing the optimized native build tools for cross env" pprint 3 "log: ${NANO_LOG}/_.native_xtools" ( nano_make_install_env set -o xtrace cd "${NANO_SRC}" ${NANO_MAKE} native-xtools DESTDIR="${NANO_WORLDDIR}" ) > ${NANO_LOG}/_.native_xtools 2>&1 ) # # Run the requested set of early customization scripts, run before # buildworld. # run_early_customize() { pprint 2 "run early customize scripts" for c in $NANO_EARLY_CUSTOMIZE do pprint 2 "early customize \"$c\"" pprint 3 "log: ${NANO_LOG}/_.early_cust.$c" pprint 4 "`type $c`" { set -x ; $c ; set +x ; } >${NANO_LOG}/_.early_cust.$c 2>&1 done } # # Run the requested set of customization scripts, run after we've # done an installworld, installed the etc files, installed the kernel # and tweaked them in the standard way. # run_customize ( ) ( pprint 2 "run customize scripts" for c in $NANO_CUSTOMIZE do pprint 2 "customize \"$c\"" pprint 3 "log: ${NANO_LOG}/_.cust.$c" pprint 4 "`type $c`" ( set -x ; $c ) > ${NANO_LOG}/_.cust.$c 2>&1 done ) # # Run any last-minute customization commands after we've had a chance to # setup nanobsd, prune empty dirs from /usr, etc # run_late_customize ( ) ( pprint 2 "run late customize scripts" for c in $NANO_LATE_CUSTOMIZE do pprint 2 "late customize \"$c\"" pprint 3 "log: ${NANO_LOG}/_.late_cust.$c" pprint 4 "`type $c`" ( set -x ; $c ) > ${NANO_LOG}/_.late_cust.$c 2>&1 done ) # # Hook called after we run all the late customize commands, but # before we invoke the disk imager. The nopriv build uses it to # read in the meta log, apply the changes other parts of nanobsd # have been recording their actions. It's not anticipated that # a user's cfg file would override this. # fixup_before_diskimage ( ) ( # Run the deduplication script that takes the matalog journal and # combines multiple entries for the same file (see source for # details). We take the extra step of removing the size keywords. This # script, and many of the user scripts, copies, appeneds and otherwise # modifies files in the build, changing their sizes. These actions are # impossible to trap, so go ahead remove the size= keyword. For this # narrow use, it doesn't buy us any protection and just gets in the way. # The dedup tool's output must be sorted due to limitations in awk. if [ -n "${NANO_METALOG}" ]; then pprint 2 "Fixing metalog" cp ${NANO_METALOG} ${NANO_METALOG}.pre echo "/set uname=${NANO_DEF_UNAME} gname=${NANO_DEF_GNAME}" > ${NANO_METALOG} cat ${NANO_METALOG}.pre | ${NANO_TOOLS}/mtree-dedup.awk | \ sed -e 's/ size=[0-9][0-9]*//' | sort >> ${NANO_METALOG} fi ) setup_nanobsd ( ) ( pprint 2 "configure nanobsd setup" pprint 3 "log: ${NANO_LOG}/_.dl" ( cd "${NANO_WORLDDIR}" # Move /usr/local/etc to /etc/local so that the /cfg stuff # can stomp on it. Otherwise packages like ipsec-tools which # have hardcoded paths under ${prefix}/etc are not tweakable. if [ -d usr/local/etc ] ; then ( mkdir -p etc/local cd usr/local/etc find . -print | cpio -dumpl ../../../etc/local cd .. rm -rf etc ln -s ../../etc/local etc ) fi for d in var etc do # link /$d under /conf # we use hard links so we have them both places. # the files in /$d will be hidden by the mount. mkdir -p conf/base/$d conf/default/$d find $d -print | cpio -dumpl conf/base/ done echo "$NANO_RAM_ETCSIZE" > conf/base/etc/md_size echo "$NANO_RAM_TMPVARSIZE" > conf/base/var/md_size # pick up config files from the special partition echo "mount -o ro /dev/${NANO_DRIVE}${NANO_SLICE_CFG}" > conf/default/etc/remount # Put /tmp on the /var ramdisk (could be symlink already) tgt_dir2symlink tmp var/tmp ) > ${NANO_LOG}/_.dl 2>&1 ) setup_nanobsd_etc ( ) ( pprint 2 "configure nanobsd /etc" ( cd "${NANO_WORLDDIR}" # create diskless marker file touch etc/diskless [ -n "${NANO_NOPRIV_BUILD}" ] && chmod 666 etc/defaults/rc.conf # Make root filesystem R/O by default echo "root_rw_mount=NO" >> etc/defaults/rc.conf # Disable entropy file, since / is read-only /var/db/entropy should be enough? echo "entropy_file=NO" >> etc/defaults/rc.conf [ -n "${NANO_NOPRIV_BUILD}" ] && chmod 444 etc/defaults/rc.conf # save config file for scripts echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf echo "/dev/${NANO_DRIVE}${NANO_ROOT} / ufs ro 1 1" > etc/fstab echo "/dev/${NANO_DRIVE}${NANO_SLICE_CFG} /cfg ufs rw,noauto 2 2" >> etc/fstab mkdir -p cfg ) ) prune_usr ( ) ( # Remove all empty directories in /usr find "${NANO_WORLDDIR}"/usr -type d -depth -print | while read d do rmdir $d > /dev/null 2>&1 || true done ) newfs_part ( ) ( local dev mnt lbl dev=$1 mnt=$2 lbl=$3 echo newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev} newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev} mount -o async ${dev} ${mnt} ) # Convenient spot to work around any umount issues that your build environment # hits by overriding this method. nano_umount ( ) ( umount ${1} ) populate_slice ( ) ( local dev dir mnt lbl dev=$1 dir=$2 mnt=$3 lbl=$4 echo "Creating ${dev} (mounting on ${mnt})" newfs_part ${dev} ${mnt} ${lbl} if [ -n "${dir}" -a -d "${dir}" ]; then echo "Populating ${lbl} from ${dir}" cd "${dir}" find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)' | cpio -dumpv ${mnt} fi df -i ${mnt} nano_umount ${mnt} ) populate_cfg_slice ( ) ( populate_slice "$1" "$2" "$3" "$4" ) populate_data_slice ( ) ( populate_slice "$1" "$2" "$3" "$4" ) create_diskimage ( ) ( pprint 2 "build diskimage" pprint 3 "log: ${NANO_LOG}/_.di" ( echo $NANO_MEDIASIZE $NANO_IMAGES \ $NANO_SECTS $NANO_HEADS \ $NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE | awk ' { printf "# %s\n", $0 # size of cylinder in sectors cs = $3 * $4 # number of full cylinders on media cyl = int ($1 / cs) # output fdisk geometry spec, truncate cyls to 1023 if (cyl <= 1023) print "g c" cyl " h" $4 " s" $3 else print "g c" 1023 " h" $4 " s" $3 if ($7 > 0) { # size of data partition in full cylinders dsl = int (($7 + cs - 1) / cs) } else { dsl = 0; } # size of config partition in full cylinders csl = int (($6 + cs - 1) / cs) if ($5 == 0) { # size of image partition(s) in full cylinders isl = int ((cyl - dsl - csl) / $2) } else { isl = int (($5 + cs - 1) / cs) } # First image partition start at second track print "p 1 165 " $3, isl * cs - $3 c = isl * cs; # Second image partition (if any) also starts offset one # track to keep them identical. if ($2 > 1) { print "p 2 165 " $3 + c, isl * cs - $3 c += isl * cs; } # Config partition starts at cylinder boundary. print "p 3 165 " c, csl * cs c += csl * cs # Data partition (if any) starts at cylinder boundary. if ($7 > 0) { print "p 4 165 " c, dsl * cs } else if ($7 < 0 && $1 > c) { print "p 4 165 " c, $1 - c } else if ($1 < c) { print "Disk space overcommitted by", \ c - $1, "sectors" > "/dev/stderr" exit 2 } # Force slice 1 to be marked active. This is necessary # for booting the image from a USB device to work. print "a 1" } ' > ${NANO_LOG}/_.fdisk IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME} MNT=${NANO_OBJ}/_.mnt mkdir -p ${MNT} if [ "${NANO_MD_BACKING}" = "swap" ] ; then MD=`mdconfig -a -t swap -s ${NANO_MEDIASIZE} -x ${NANO_SECTS} \ -y ${NANO_HEADS}` else echo "Creating md backing file..." rm -f ${IMG} dd if=/dev/zero of=${IMG} seek=${NANO_MEDIASIZE} count=0 MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \ -y ${NANO_HEADS}` fi trap "echo 'Running exit trap code' ; df -i ${MNT} ; nano_umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT fdisk -i -f ${NANO_LOG}/_.fdisk ${MD} fdisk ${MD} # XXX: params # XXX: pick up cached boot* files, they may not be in image anymore. if [ -f ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ]; then boot0cfg -B -b ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ${NANO_BOOT0CFG} ${MD} fi if [ -f ${NANO_WORLDDIR}/boot/boot ]; then bsdlabel -w -B -b ${NANO_WORLDDIR}/boot/boot ${MD}${NANO_SLICE_ROOT} else bsdlabel -w ${MD}${NANO_SLICE_ROOT} fi bsdlabel ${MD}${NANO_SLICE_ROOT} # Create first image populate_slice /dev/${MD}${NANO_ROOT} ${NANO_WORLDDIR} ${MNT} "${NANO_ROOT}" mount /dev/${MD}${NANO_ROOT} ${MNT} echo "Generating mtree..." ( cd "${MNT}" && mtree -c ) > ${NANO_LOG}/_.mtree ( cd "${MNT}" && du -k ) > ${NANO_LOG}/_.du nano_umount "${MNT}" if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then # Duplicate to second image (if present) echo "Duplicating to second image..." dd conv=sparse if=/dev/${MD}${NANO_SLICE_ROOT} of=/dev/${MD}${NANO_SLICE_ALTROOT} bs=64k mount /dev/${MD}${NANO_ALTROOT} ${MNT} for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab do sed -i "" "s=${NANO_DRIVE}${NANO_SLICE_ROOT}=${NANO_DRIVE}${NANO_SLICE_ALTROOT}=g" $f done nano_umount ${MNT} # Override the label from the first partition so we # don't confuse glabel with duplicates. if [ -n "${NANO_LABEL}" ]; then tunefs -L ${NANO_LABEL}"${NANO_ALTROOT}" /dev/${MD}${NANO_ALTROOT} fi fi # Create Config slice populate_cfg_slice /dev/${MD}${NANO_SLICE_CFG} "${NANO_CFGDIR}" ${MNT} "${NANO_SLICE_CFG}" # Create Data slice, if any. if [ -n "$NANO_SLICE_DATA" -a "$NANO_SLICE_CFG" = "$NANO_SLICE_DATA" -a \ "$NANO_DATASIZE" -ne 0 ]; then pprint 2 "NANO_SLICE_DATA is the same as NANO_SLICE_CFG, fix." exit 2 fi if [ $NANO_DATASIZE -ne 0 -a -n "$NANO_SLICE_DATA" ] ; then populate_data_slice /dev/${MD}${NANO_SLICE_DATA} "${NANO_DATADIR}" ${MNT} "${NANO_SLICE_DATA}" fi if [ "${NANO_MD_BACKING}" = "swap" ] ; then if [ ${NANO_IMAGE_MBRONLY} ]; then echo "Writing out _.disk.mbr..." dd if=/dev/${MD} of=${NANO_DISKIMGDIR}/_.disk.mbr bs=512 count=1 else echo "Writing out ${NANO_IMGNAME}..." dd if=/dev/${MD} of=${IMG} bs=64k fi echo "Writing out ${NANO_IMGNAME}..." dd conv=sparse if=/dev/${MD} of=${IMG} bs=64k fi if ${do_copyout_partition} ; then echo "Writing out _.disk.image..." dd conv=sparse if=/dev/${MD}${NANO_SLICE_ROOT} of=${NANO_DISKIMGDIR}/_.disk.image bs=64k fi mdconfig -d -u $MD trap - 1 2 15 trap nano_cleanup EXIT ) > ${NANO_LOG}/_.di 2>&1 ) last_orders ( ) ( # Redefine this function with any last orders you may have # after the build completed, for instance to copy the finished # image to a more convenient place: # cp ${NANO_DISKIMGDIR}/_.disk.image /home/ftp/pub/nanobsd.disk true ) ####################################################################### # # Optional convenience functions. # ####################################################################### ####################################################################### # Common Flash device geometries # FlashDevice ( ) { if [ -d ${NANO_TOOLS} ] ; then . ${NANO_TOOLS}/FlashDevice.sub else . ${NANO_SRC}/${NANO_TOOLS}/FlashDevice.sub fi sub_FlashDevice $1 $2 } ####################################################################### # USB device geometries # # Usage: # UsbDevice Generic 1000 # a generic flash key sold as having 1GB # # This function will set NANO_MEDIASIZE, NANO_HEADS and NANO_SECTS for you. # # Note that the capacity of a flash key is usually advertised in MB or # GB, *not* MiB/GiB. As such, the precise number of cylinders available # for C/H/S geometry may vary depending on the actual flash geometry. # # The following generic device layouts are understood: # generic An alias for generic-hdd. # generic-hdd 255H 63S/T xxxxC with no MBR restrictions. # generic-fdd 64H 32S/T xxxxC with no MBR restrictions. # # The generic-hdd device is preferred for flash devices larger than 1GB. # UsbDevice ( ) { a1=`echo $1 | tr '[:upper:]' '[:lower:]'` case $a1 in generic-fdd) NANO_HEADS=64 NANO_SECTS=32 NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 )) ;; generic|generic-hdd) NANO_HEADS=255 NANO_SECTS=63 NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 )) ;; *) echo "Unknown USB flash device" exit 2 ;; esac } ####################################################################### # Setup serial console cust_comconsole ( ) ( # Enable getty on console sed -i "" -e /tty[du]0/s/off/on/ ${NANO_WORLDDIR}/etc/ttys # Disable getty on syscons devices sed -i "" -e '/^ttyv[0-8]/s/ on/ off/' ${NANO_WORLDDIR}/etc/ttys # Tell loader to use serial console early. echo "${NANO_BOOT2CFG}" > ${NANO_WORLDDIR}/boot.config ) ####################################################################### # Allow root login via ssh cust_allow_ssh_root ( ) ( sed -i "" -e '/PermitRootLogin/s/.*/PermitRootLogin yes/' \ ${NANO_WORLDDIR}/etc/ssh/sshd_config ) ####################################################################### # Install the stuff under ./Files cust_install_files ( ) ( cd "${NANO_TOOLS}/Files" find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)' | cpio -Ldumpv ${NANO_WORLDDIR} if [ -n "${NANO_CUST_FILES_MTREE}" -a -f ${NANO_CUST_FILES_MTREE} ]; then CR "mtree -eiU -p /" <${NANO_CUST_FILES_MTREE} fi ) ####################################################################### # Install packages from ${NANO_PACKAGE_DIR} cust_pkgng ( ) ( mkdir -p ${NANO_WORLDDIR}/usr/local/etc local PKG_CONF="${NANO_WORLDDIR}/usr/local/etc/pkg.conf" local PKGCMD="env ASSUME_ALWAYS_YES=YES PKG_DBDIR=${NANO_PKG_META_BASE}/pkg SIGNATURE_TYPE=none /usr/sbin/pkg" # Ensure pkg.conf points pkg to where the package meta data lives. touch ${PKG_CONF} if grep -Eiq '^PKG_DBDIR:.*' ${PKG_CONF}; then sed -i -e "\|^PKG_DBDIR:.*|Is||PKG_DBDIR: "\"${NANO_PKG_META_BASE}/pkg\""|" ${PKG_CONF} else echo "PKG_DBDIR: \"${NANO_PKG_META_BASE}/pkg\"" >> ${PKG_CONF} fi # If the package directory doesn't exist, we're done. if [ ! -d ${NANO_PACKAGE_DIR} ]; then echo "DONE 0 packages" return 0 fi # Find a pkg-* package for x in `find -s ${NANO_PACKAGE_DIR} -iname 'pkg-*'`; do _NANO_PKG_PACKAGE=`basename "$x"` done if [ -z "${_NANO_PKG_PACKAGE}" -o ! -f "${NANO_PACKAGE_DIR}/${_NANO_PKG_PACKAGE}" ]; then echo "FAILED: need a pkg/ package for bootstrapping" exit 2 fi NANO_PACKAGE_LIST="${_NANO_PKG_PACKAGE} ${NANO_PACKAGE_LIST}" # Mount packages into chroot mkdir -p ${NANO_WORLDDIR}/_.p mount -t nullfs -o noatime -o ro ${NANO_PACKAGE_DIR} ${NANO_WORLDDIR}/_.p trap "umount ${NANO_WORLDDIR}/_.p ; rm -rf ${NANO_WORLDDIR}/_.p" 1 2 15 EXIT # Install packages todo="$(echo "${NANO_PACKAGE_LIST}" | awk '{ print NF }')" echo "=== TODO: $todo" echo "${NANO_PACKAGE_LIST}" echo "===" for _PKG in ${NANO_PACKAGE_LIST}; do CR "${PKGCMD} add /_.p/${_PKG}" done CR0 "${PKGCMD} info" trap - 1 2 15 EXIT umount ${NANO_WORLDDIR}/_.p rm -rf ${NANO_WORLDDIR}/_.p ) ####################################################################### # Convenience function: # Register all args as early customize function to run just before # build commences. early_customize_cmd () { NANO_EARLY_CUSTOMIZE="$NANO_EARLY_CUSTOMIZE $*" } ####################################################################### # Convenience function: # Register all args as customize function. customize_cmd ( ) { NANO_CUSTOMIZE="$NANO_CUSTOMIZE $*" } ####################################################################### # Convenience function: # Register all args as late customize function to run just before # image creation. late_customize_cmd ( ) { NANO_LATE_CUSTOMIZE="$NANO_LATE_CUSTOMIZE $*" } ####################################################################### # # All set up to go... # ####################################################################### # Progress Print # Print $2 at level $1. pprint ( ) ( if [ "$1" -le $PPLEVEL ]; then runtime=$(( `date +%s` - $NANO_STARTTIME )) printf "%s %.${1}s %s\n" "`date -u -r $runtime +%H:%M:%S`" "#####" "$2" 1>&3 fi ) usage ( ) { ( echo "Usage: $0 [-bfiKknqvw] [-c config_file]" echo " -b suppress builds (both kernel and world)" echo " -c specify config file" echo " -f suppress code slice extraction" echo " -i suppress disk image build" echo " -K suppress installkernel" echo " -k suppress buildkernel" echo " -n add -DNO_CLEAN to buildworld, buildkernel, etc" echo " -q make output more quiet" echo " -v make output more verbose" echo " -w suppress buildworld" ) 1>&2 exit 2 } ####################################################################### # Setup and Export Internal variables # export_var ( ) { # Don't wawnt a subshell var=$1 # Lookup value of the variable. eval val=\$$var pprint 3 "Setting variable: $var=\"$val\"" export $1 } # Call this function to set defaults _after_ parsing options. # dont want a subshell otherwise variable setting is thrown away. set_defaults_and_export ( ) { : ${NANO_OBJ:=/usr/obj/nanobsd.${NANO_NAME}} : ${MAKEOBJDIRPREFIX:=${NANO_OBJ}} : ${NANO_DISKIMGDIR:=${NANO_OBJ}} : ${NANO_WORLDDIR:=${NANO_OBJ}/_.w} : ${NANO_LOG:=${NANO_OBJ}} NANO_MAKE_CONF_BUILD=${MAKEOBJDIRPREFIX}/make.conf.build NANO_MAKE_CONF_INSTALL=${NANO_OBJ}/make.conf.install # Override user's NANO_DRIVE if they specified a NANO_LABEL [ -n "${NANO_LABEL}" ] && NANO_DRIVE="ufs/${NANO_LABEL}" || true # Set a default NANO_TOOLS to NANO_SRC/NANO_TOOLS if it exists. [ ! -d "${NANO_TOOLS}" ] && [ -d "${NANO_SRC}/${NANO_TOOLS}" ] && \ NANO_TOOLS="${NANO_SRC}/${NANO_TOOLS}" || true [ -n "${NANO_NOPRIV_BUILD}" ] && [ -z "${NANO_METALOG}" ] && \ NANO_METALOG=${NANO_OBJ}/_.metalog || true NANO_STARTTIME=`date +%s` pprint 3 "Exporting NanoBSD variables" export_var MAKEOBJDIRPREFIX export_var NANO_ARCH export_var NANO_CODESIZE export_var NANO_CONFSIZE export_var NANO_CUSTOMIZE export_var NANO_DATASIZE export_var NANO_DRIVE export_var NANO_HEADS export_var NANO_IMAGES export_var NANO_IMGNAME export_var NANO_MAKE export_var NANO_MAKE_CONF_BUILD export_var NANO_MAKE_CONF_INSTALL export_var NANO_MEDIASIZE export_var NANO_NAME export_var NANO_NEWFS export_var NANO_OBJ export_var NANO_PMAKE export_var NANO_SECTS export_var NANO_SRC export_var NANO_TOOLS export_var NANO_WORLDDIR export_var NANO_BOOT0CFG export_var NANO_BOOTLOADER export_var NANO_LABEL export_var NANO_MODULES export_var NANO_NOPRIV_BUILD export_var NANO_METALOG export_var NANO_LOG export_var SRCCONF export_var SRC_ENV_CONF } Index: head/tools/tools/nanobsd/dhcpd/common =================================================================== --- head/tools/tools/nanobsd/dhcpd/common (revision 298880) +++ head/tools/tools/nanobsd/dhcpd/common (revision 298881) @@ -1,275 +1,275 @@ # $FreeBSD$ #- # Copyright (c) 2014 Warner Losh. All Rights Reserved. # Copyright (c) 2010 iXsystems, Inc., All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL iXsystems, Inc OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This file is heavily derived from both Sam Leffler's Avilia config, # as well as the BSDRP project's config file. Neither of these have # an explicit copyright/license statement, but are implicitly BSDL. This # example has been taken from the FreeNAS project (an early version) and # simplified to meet the needs of the example. # # NB: You want the other file NANO_PMAKE="make -j $(sysctl -n hw.ncpu)" NANO_CFG_BASE=$(pwd) NANO_CFG_BASE=${NANO_CFG_BASE%/dhcpd} NANO_SRC=$(pwd) NANO_SRC=${NANO_SRC%/tools/tools/nanobsd/dhcpd} NANO_OBJ=${NANO_SRC}/../dhcpd/obj # Where cust_pkg() finds packages to install #XXX: Is this the right place? #NANO_PORTS=$(realpath ${NANO_SRC}/../ports) NANO_PORTS=/usr/ports NANO_PACKAGE_DIR=${NANO_SRC}/${NANO_TOOLS}/Pkg NANO_DATADIR=${NANO_OBJ}/_.data NANO_DATASIZE=40960 NANO_INIT_IMG2=0 unset MAKEOBJDIRPREFIX # this to go into nanobsd.sh NANO_PORTS=${NANO_PORTS:-/usr/ports} customize_cmd cust_allow_ssh_root add_etc_make_conf() { touch ${NANO_WORLDDIR}/etc/make.conf } customize_cmd add_etc_make_conf clean_usr_local() { LOCAL_DIR=${NANO_WORLDDIR}/usr/local pprint 2 "Clean and create world directory (${LOCAL_DIR})" if rm -rf ${LOCAL_DIR}/ > /dev/null 2>&1 ; then true else chflags -R noschg ${LOCAL_DIR}/ rm -rf ${LOCAL_DIR}/ fi for f in bin etc lib libdata libexec sbin share; do mkdir -p ${LOCAL_DIR}/$f done } customize_cmd clean_usr_local cust_install_machine_files() { echo "cd ${NANO_CFG_BASE}/Files" cd ${NANO_CFG_BASE}/Files find . -print | grep -Ev '/(CVS|\.svn)' | cpio -dumpv ${NANO_WORLDDIR} } customize_cmd cust_install_files customize_cmd cust_install_machine_files buildenv() { cd ${NANO_SRC} env __MAKE_CONF=${NANO_MAKE_CONF_BUILD} DESTDIR=${NANO_WORLDDIR} make buildenv } NANO_MAKEFS="makefs -B big \ -o bsize=4096,fsize=512,density=8192,optimization=space" export NANO_MAKEFS # NB: leave c++ enabled so devd can be built CONF_BUILD=" WITHOUT_ACPI=true WITHOUT_ATM=true WITHOUT_AUDIT=true WITHOUT_BIND_DNSSEC=true WITHOUT_BIND_ETC=true WITHOUT_BIND_LIBS_LWRES=true WITHOUT_BLUETOOTH=true WITHOUT_CALENDAR=true WITHOUT_CVS=true WITHOUT_DICT=true WITHOUT_EXAMPLES=true WITHOUT_FORTRAN=true WITHOUT_GAMES=true WITHOUT_GCOV=true WITHOUT_GPIB=true WITHOUT_HTML=true WITHOUT_I4B=true WITHOUT_IPFILTER=true WITHOUT_IPX=true WITHOUT_LIBKSE=true WITHOUT_LOCALES=true WITHOUT_LPR=true WITHOUT_MAN=true WITHOUT_NETCAT=true WITHOUT_NIS=true WITHOUT_NLS=true WITHOUT_NS_CACHING=true WITHOUT_OBJC=true WITHOUT_PROFILE=true WITHOUT_RCMDS=true WITHOUT_SENDMAIL=true WITHOUT_SHAREDOCS=true WITHOUT_SYSCONS=true WITHOUT_LIB32=true " CONF_INSTALL="$CONF_BUILD INSTALL_NODEBUG=t NOPORTDOCS=t NO_INSTALL_MANPAGES=t " # The following would help... # WITHOUT_TOOLCHAIN=true can't build ports # WITHOUT_INSTALLLIB=true libgcc.a # # from the build # WITHOUT_INFO=true makeinfo # WITHOUT_RCS=true PKG_ONLY_MAKE_CONF=" WITHOUT_TOOLCHAIN=true WITHOUT_INSTALLLIB=true WITHOUT_INFO=true WITHOUT_RCS=true " NANO_PACKAGE_ONLY=1 # install a package from a pre-built binary do_add_pkg () { # Need to create ${NANO_OBJ}/ports in this add_pkg_${port} function set -x mkdir -p ${NANO_OBJ}/ports/distfiles mkdir -p ${NANO_OBJ}/ports/packages mkdir -p ${NANO_WORLDDIR}/usr/ports/packages mkdir -p ${NANO_WORLDDIR}/usr/ports/distfiles mount -t nullfs -o noatime ${NANO_OBJ}/ports/packages \ ${NANO_WORLDDIR}/usr/ports/packages mount -t nullfs -o noatime ${NANO_OBJ}/ports/distfiles \ ${NANO_WORLDDIR}/usr/ports/distfiles CR env ASSUME_ALWAYS_YES=YES SIGNATURE_TYPE=none /usr/sbin/pkg add /usr/ports/packages/All/$1.txz umount ${NANO_WORLDDIR}/usr/ports/distfiles umount ${NANO_WORLDDIR}/usr/ports/packages rmdir ${NANO_WORLDDIR}/usr/ports/packages rmdir ${NANO_WORLDDIR}/usr/ports/distfiles rmdir ${NANO_WORLDDIR}/usr/ports set +x } # Build a port (with the side effect of creating a package) do_add_port () { local port_path port_path=$1 shift set -x # Need to create ${NANO_OBJ}/ports in this add_port_${port} function mkdir -p ${NANO_OBJ}/ports/distfiles mkdir -p ${NANO_OBJ}/ports/packages mkdir -p ${NANO_PORTS}/packages mkdir -p ${NANO_PORTS}/distfiles mkdir -p ${NANO_WORLDDIR}/usr/src mkdir -p ${NANO_WORLDDIR}/usr/ports mount -t nullfs -o noatime ${NANO_SRC} ${NANO_WORLDDIR}/usr/src mount -t nullfs -o noatime ${NANO_PORTS} ${NANO_WORLDDIR}/usr/ports mount -t nullfs -o noatime ${NANO_OBJ}/ports/packages \ ${NANO_WORLDDIR}/usr/ports/packages mount -t nullfs -o noatime ${NANO_OBJ}/ports/distfiles \ ${NANO_WORLDDIR}/usr/ports/distfiles mkdir -p ${NANO_WORLDDIR}/dev mount -t devfs devfs ${NANO_WORLDDIR}/dev mkdir -p ${NANO_WORLDDIR}/usr/workdir cp /etc/resolv.conf ${NANO_WORLDDIR}/etc/resolv.conf # OK, a little inefficient, but likely not enough to worry about. CR ldconfig /lib /usr/lib /usr/local/lib CR ldconfig -R CR ldconfig -r # Improvement: Don't know why package-recursive don't works here CR "env UNAME_p=${NANO_ARCH} TARGET=${NANO_ARCH} \ TARGET_ARCH=${NANO_ARCH} PORTSDIR=${NANO_PORTS} make \ __MAKE_CONF=${NANO_MAKE_CONF_BUILD} \ WRKDIRPREFIX=/usr/workdir -C /usr/ports/$port_path \ package-recursive BATCH=yes $* clean FORCE_PKG_REGISTER=t" rm ${NANO_WORLDDIR}/etc/resolv.conf rm -rf ${NANO_WORLDDIR}/usr/obj rm -rf ${NANO_WORLDDIR}/usr/workdir umount ${NANO_WORLDDIR}/dev umount ${NANO_WORLDDIR}/usr/ports/packages umount ${NANO_WORLDDIR}/usr/ports/distfiles umount ${NANO_WORLDDIR}/usr/ports umount ${NANO_WORLDDIR}/usr/src set +x } # Need to check if this function works with cross-compiling architecture!!!! # Recursive complex fonction: Generate one function for each ports add_port () { local port_path=$1 local port=`echo $1 | sed -e 's/\//_/'` shift - # Check if package allready exist + # Check if package already exist # Need to: # 1. check ARCH of this package! # 2. Add a trap cd ${NANO_PORTS}/${port_path} PKG_NAME=`env PORTSDIR=${NANO_PORTS} make __MAKE_CONF=${NANO_MAKE_CONF_BUILD} package-name` if [ -f ${NANO_OBJ}/ports/packages/All/${PKG_NAME}.txz ]; then # Pkg file found: Generate add_pkg_NAME function eval " add_pkg_${port} () { do_add_pkg ${PKG_NAME} } customize_cmd add_pkg_${port} " else # No pkg file: Generate add_port_NAME function eval " add_port_${port} () { do_add_port ${port_path} $* } customize_cmd add_port_${port} " NANO_PACKAGE_ONLY=0 fi } die() { echo "$*" exit 1 } # Automatically include the packaging port here so it is always first so it # builds the port and adds the package so we can add other packages. add_port ports-mgmt/pkg rp=$(realpath ${NANO_OBJ}/) __a=`mount | grep ${rp} | awk '{print length($3), $3;}' | sort -rn | awk '{$1=""; print;}'` if [ -n "$__a" ]; then echo "unmounting $__a" umount $__a fi NANO_BOOTLOADER="boot/boot0" Index: head/tools/tools/nanobsd/embedded/README =================================================================== --- head/tools/tools/nanobsd/embedded/README (revision 298880) +++ head/tools/tools/nanobsd/embedded/README (revision 298881) @@ -1,49 +1,49 @@ $FreeBSD$ Example for creating many different builds (including different arch) from a common set of files, as well as building natively using qemu user space emulation. This creates a simple appliance that uses dnsmasq to serve DNS and DHCPd. This is a work in progress. Generally, to build this you should cd tools/tools/nanobsd/embedded sudo sh ../nanobsd.sh -c foo.cfg Some features: Image size is minimal, we grow the last partition on first boot to fill the media. Images are both as easy as possible to construct, as well as easy as possible to expand. Config Short description beaglebone.cfg Create a bootable beaglebone image qemu-amd64.cfg Create a bootable amd64 image for qemu (W) qemu-i386.cfg Create a bootable i386 image for qemu (W) qemu-mips.cfg Create a bootable mips malta board image for qemu qemu-mips64.cfg Create a bootable mips malta board (64-bit mode) image for qemu qemu-powerpc.cfg Create a bootable 32-bit powerpc image for qemu qemu-powerpc64.cfg Create a bootable 64-bit IBM-flavor image for qemu qemu-sparc64.cfg Create a bootable sparc64 image for qemu rpi.cfg Create a bootable image for Raspberry Pi B rpi2.cfg Create a bootable image for Raspberry Pi2 sam9260ek.cfg Create a bootable image for an Atmel SAM9260-EK - evaluation board (still needs a kenrel loaded + evaluation board (still needs a kernel loaded into dataflash or NAND, so experimental). sam9g20ek.cfg Create a bootable image for an Atmel SAM9G20-EK - evaluation board (still needs a kenrel loaded + evaluation board (still needs a kernel loaded into dataflash or NAND, so experimental). Also works on many after-market boards that are somewhat - compatible with the refernce board. + compatible with the references board. QEMU command lines for serial console access i386: qemu-system-i386 -m 512 -hda _.disk.image.qemu-i386.qcow2 -nographic amd64: qemu-system-amd64 -m 512 -hda _.disk.image.qemu-amd64.qcow2 -nographic Index: head/tools/tools/nanobsd/embedded/common =================================================================== --- head/tools/tools/nanobsd/embedded/common (revision 298880) +++ head/tools/tools/nanobsd/embedded/common (revision 298881) @@ -1,655 +1,655 @@ # $FreeBSD$ #- # Copyright (c) 2015 Warner Losh. All Rights Reserved. # Copyright (c) 2010-2011 iXsystems, Inc., All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL iXsystems, Inc OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This file is heavily derived from both Sam Leffler's Avilia config, # as well as the BSDRP project's config file. Neither of these have # an explicit copyright/license statement, but are implicitly BSDL. This # example has been taken from the FreeNAS project (an early version) and # simplified to meet the needs of the example. # # NB: You want the other file as the command line arg :) # Missing in base: # o mkimg setting active partition # o mkimg starting at arbitrary offset (needed for A10, et al) -# o mtools still needed becuase we have no makefs -t msdos +# o mtools still needed because we have no makefs -t msdos # o nanobsd doesn't record changes to WORLDTEMP in customization # scripts yet, so we have kludge to pick up all files # o easy way for pkg to grab files from other repos and put that # data on the image # o Need to have some way to create / resize the s4 slice to do ping # pong bouncing between s3 and s4 for an arbitrary image. we can resize # one slice, not two # o hints in the uboot ports for how to create the image # # Missing here # o documentation for how to run the qemu images # o msdos mtools fallback # o special boot for !x86 !arm platforms # o qemu image for arm # o qemu image for aarch64 # o qemu image for armv6/armv7 # o easy support for different image / vm formats # o need to promote much of this to nanobsd.sh and friends # o uses old kludge to build image w/o ownership being right # for many files. Should move to mtree-dedup.awk. # o support for EFI images # o support for GPT partitioning # # Long Term # o common tooling for creating images for odd-ball platforms # o support for boot loaders other than uboot in the image # or via special insturctions # o No pony support. Sadly, you cannot have a pony. # if [ -z $NANO_NAME ]; then echo "NANO_NAME not defined. Use foo.cfg instead." fi NANO_SLICE_FAT_SIZE=32m NANO_SLICE_CFG_SIZE=32m NANO_BOOT2CFG="-P -S115200" NANO_RAM_ETCSIZE=8192 NANO_RAM_TMPVARSIZE=8192 NANO_IMAGES=2 NANO_PMAKE="make -j $(sysctl -n hw.ncpu)" NANO_CFG_BASE=$(pwd) NANO_CFG_BASE=$(realpath ${NANO_CFG_BASE}/..) NANO_SRC=$(realpath ${NANO_CFG_BASE}/../../..) #### XXX share obj if [ -z ${NANO_CPUTYPE} ]; then NANO_OBJ=${NANO_SRC}/../embedded/obj else # Alas, I can't set OBJTREE to ${MACHINE}.${MACHINE_ARCH}.${CPUTYPE} # so this will have to do until I can. NANO_OBJ=${NANO_SRC}/../embedded/obj.${NANO_CPUTYPE} fi NANO_LOG=${NANO_OBJ}/../${NANO_NAME} NANO_DISKIMGDIR=${NANO_OBJ}/../images NANO_WORLDDIR=${NANO_LOG}/_.w NANO_INIT_IMG2=0 NANO_NOPRIV_BUILD=t unset MAKEOBJDIRPREFIX mkdir -p ${NANO_OBJ} NANO_OBJ=$(realpath ${NANO_OBJ}) mkdir -p ${NANO_LOG} NANO_LOG=$(realpath ${NANO_LOG}) mkdir -p ${NANO_IMAGES} NANO_IMAGES=$(realpath ${NANO_IMAGES}) mkdir -p ${NANO_WORLDDIR} NANO_WORLDDIR=$(realpath ${NANO_WORLDDIR}) mkdir -p ${NANO_DISKIMGDIR} NANO_DISKIMGDIR=$(realpath ${NANO_DISKIMGDIR}) NANO_FAT_DIR=${NANO_LOG}/_.fat customize_cmd cust_allow_ssh_root add_etc_make_conf ( ) ( touch ${NANO_WORLDDIR}/etc/make.conf ) customize_cmd add_etc_make_conf cust_install_machine_files ( ) ( echo "cd ${NANO_CFG_BASE}/Files" cd ${NANO_CFG_BASE}/Files find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)' | cpio -dumpv ${NANO_WORLDDIR} ) customize_cmd cust_install_files customize_cmd cust_install_machine_files # NB: leave c++ enabled so devd can be built CONF_BUILD=" WITHOUT_ACPI=true WITHOUT_ATM=true WITHOUT_AUDIT=true WITHOUT_BIND_DNSSEC=true WITHOUT_BIND_ETC=true WITHOUT_BIND_LIBS_LWRES=true WITHOUT_BLUETOOTH=true WITHOUT_CALENDAR=true WITHOUT_CVS=true WITHOUT_DICT=true WITHOUT_EXAMPLES=true WITHOUT_FORTRAN=true WITHOUT_GAMES=true WITHOUT_GCOV=true WITHOUT_GPIB=true WITHOUT_HTML=true WITHOUT_I4B=true WITHOUT_IPFILTER=true WITHOUT_IPX=true WITHOUT_LIBKSE=true WITHOUT_LOCALES=true WITHOUT_LPR=true WITHOUT_MAN=true WITHOUT_NETCAT=true WITHOUT_NIS=true WITHOUT_NLS=true WITHOUT_NS_CACHING=true WITHOUT_OBJC=true WITHOUT_PROFILE=true WITHOUT_RCMDS=true WITHOUT_SENDMAIL=true WITHOUT_SHAREDOCS=true WITHOUT_SYSCONS=true WITHOUT_LIB32=true WITHOUT_TESTS=true WITHOUT_DEBUG_FILES=t WITHOUT_KERNEL_SYMBOLS=t " CONF_INSTALL="$CONF_BUILD INSTALL_NODEBUG=t NOPORTDOCS=t NO_INSTALL_MANPAGES=t " # The following would help... # WITHOUT_TOOLCHAIN=true can't build ports # WITHOUT_INSTALLLIB=true libgcc.a # # from the build # WITHOUT_INFO=true makeinfo # WITHOUT_RCS=true PKG_ONLY_MAKE_CONF=" WITHOUT_TOOLCHAIN=true WITHOUT_INSTALLLIB=true WITHOUT_INFO=true WITHOUT_RCS=true " NANO_PACKAGE_ONLY=1 # Creates images for all the formats that use MBR / GPT # split later if the #ifdef soup gets too bad. create_diskimage_gpt ( ) ( pprint 2 "build diskimage gpt ${NANO_NAME}" create_diskimage_mbr $* ) create_diskimage_mbr ( ) ( pprint 2 "build diskimage ${NANO_NAME}" pprint 3 "log: ${NANO_LOG}/_.di" ( local extra i sz fmt fmtarg bootmbr bootbsd skiparg set -o xtrace [ -z ${NANO_DISKIMAGE_FORMAT} ] || fmtarg="-f ${NANO_DISKIMAGE_FORMAT}" [ -z ${NANO_DISKIMAGE_FORMAT} ] || fmt=".${NANO_DISKIMAGE_FORMAT}" bootmbr=${NANO_BOOT_MBR:+-b ${NANO_BOOT_MBR}} bootbsd=${NANO_BOOT_BSD:+-b ${NANO_BOOT_BSD}} skiparg=${NANO_MBR_FIRST_SKIP:+-S ${NANO_MBR_FIRST_SKIP}} for i in s1 s2 s3 s4 p1 p2 p3 p4 p5 empty; do rm -fr ${NANO_LOG}/_.${i}* done # Populate the FAT partition, if needed if [ -n "${NANO_SLICE_FAT}" ]; then echo Creating MSDOS partition for kernel newfs_msdos -C ${NANO_SLICE_FAT_SIZE} -F 16 -L ${NANO_NAME} \ ${NANO_LOG}/_.${NANO_SLICE_FAT} if [ -d ${NANO_FAT_DIR} ]; then # Need to copy files from ${NANO_FATDIR} with mtools, or use # makefs -t msdos once that's supported mcopy -i ${NANO_LOG}/_.${NANO_SLICE_FAT} ${NANO_FAT_DIR}/* :: fi fi # Populate the Powerpc boot image, if needed if [ "${NANO_LAYOUT}" = powerpc64-ibm ]; then dd if=${NANO_WORLDDIR}/boot/boot1.elf of=${NANO_LOG}/_.s1 bs=800k count=1 conv=sync fi # Populate the / partition, and place it into a slice with a # bsd label [ -z ${NANO_NOPRIV_BUILD} ] || extra="-F ${NANO_METALOG}" sz=${NANO_SLICE_ROOT_SIZE:+-s ${NANO_SLICE_ROOT_SIZE}} eval "${NANO_MAKEFS_UFS}" ${extra} $sz "${NANO_LOG}/_.${NANO_ROOT}" \ "${NANO_WORLDDIR}" case ${NANO_DISK_SCHEME} in mbr) mkimg -s bsd ${bootbsd} -p freebsd-ufs:=${NANO_LOG}/_.${NANO_ROOT} \ -o ${NANO_LOG}/_.${NANO_SLICE_ROOT} eval $NANO_SLICE_CFG=freebsd eval $NANO_SLICE_ROOT=freebsd ;; gpt) eval $NANO_SLICE_CFG=freebsd-ufs eval $NANO_SLICE_ROOT=freebsd-ufs ;; esac # Populate the /cfg partition, empty if none given if [ -z "${NANO_CFGDIR}" ]; then echo "Faking cfg dir, it's empty" NANO_CFGDIR=${NANO_LOG}/_.empty mkdir -p ${NANO_CFGDIR} fi # XXX -F cfg-mtree eval "${NANO_MAKEFS_UFS}" -s ${NANO_SLICE_CFG_SIZE} \ "${NANO_LOG}/_.${NANO_SLICE_CFG}" "${NANO_CFGDIR}" # data slice not supported since we need the part for FAT for # booting # Now shuffle all the slices together into the proper layout if [ -n "$NANO_SLICE_FAT" ]; then eval $NANO_SLICE_FAT=fat16b fi out=${NANO_DISKIMGDIR}/_.disk.image.${NANO_NAME}${fmt} # below depends on https://reviews.freebsd.org/D4403 not yet in the tree # but there's problems: it marks all partitions as active, so you have to # boot off parittion 3 or 2 by hand if you're playing around with this WIP case ${NANO_LAYOUT} in std-embedded) mkimg -a 3 ${skiparg} ${fmtarg} ${bootmbr} -s mbr -p ${s1}:=${NANO_LOG}/_.s1 \ -p ${s2}:=${NANO_LOG}/_.s2 \ -p ${s3}:=${NANO_LOG}/_.s3 \ -o ${out} ;; std-x86) # s1 is cfg, s2 is /, not sure how to make that # boot (marked as active) with mkimg yet mkimg -a 2 ${fmtarg} ${bootmbr} -s mbr -p ${s1}:=${NANO_LOG}/_.s1 \ -p ${s2}:=${NANO_LOG}/_.s2 \ -o ${out} ;; std-uefi) # s1 is boot, s2 is cfg, s3 is /, not sure how to make that # boot (marked as active) with mkimg yet mkimg -a 2 ${fmtarg} ${bootmbr} -s mbr \ -p efi:=${NANO_WORLDDIR}/boot/boot1.efifat \ -p ${s2}:=${NANO_LOG}/_.s2 \ -p ${s3}:=${NANO_LOG}/_.s3 \ -o ${out} ;; std-uefi-bios) # p1 is boot for uefi, p2 is boot for gpt, p3 is cfg, p4 is / # and p5 is alt-root (after resize) mkimg -a 2 ${fmtarg} ${bootmbr} -s gpt \ -p efi:=${NANO_WORLDDIR}/boot/boot1.efifat \ -p freebsd-boot:=${NAANO_WORLDDIR}/boot/gptboot \ -p ${p3}:=${NANO_LOG}/_.p3 \ -p ${p4}:=${NANO_LOG}/_.p4 \ -o ${out} ;; powerpc64-ibm) # A lie to make the boot loader work, it boots the first BSD partition # it finds, regardless of the active flag. s2=fat16b # boot image is on a special partition, ala std-embedded, but that # partition isn't FAT with special files, but a copy of the boot # loader itself. mkimg -a 1 ${fmtarg} -s mbr -p prepboot:=${NANO_LOG}/_.s1 \ -p ${s2}:=${NANO_LOG}/_.s2 \ -p ${s3}:=${NANO_LOG}/_.s3a \ -o ${out} ;; esac rm -f ${out}.xz xz -9 --keep ${out} ) > ${NANO_LOG}/_.di 2>&1 ) die( ) { echo "$*" exit 1 } # Automatically include the packaging port here so it is always first so it # builds the port and adds the package so we can add other packages. #XXX Doesn't work for cross build, so punting until I can integreate qemu-static #XXX or poudere, both of which require priv'd execution. Or qemu-system, which #XXX is super, super slow. #add_port ports-mgmt/pkg #add_port security/sudo #add_port ftp/curl rp=$(realpath ${NANO_OBJ}/) __a=`mount | grep ${rp} | awk '{print length($3), $3;}' | sort -rn | awk '{$1=""; print;}'` if [ -n "$__a" ]; then echo "unmounting $__a" umount $__a fi if [ "$DEBUG" = 1 ]; then DEBUG_BUILD=" DEBUG_FLAGS= -g " else DEBUG_INSTALL=" INSTALL_NODEBUG= t " fi CONF_INSTALL="$CONF_BUILD ${DEBUG_BUILD} " CONF_INSTALL="$CONF_INSTALL ${DEBUG_INSTALL} " if [ "${NANO_PACKAGE_ONLY}" -eq 1 ]; then CONF_INSTALL="${CONF_INSTALL} ${PKG_ONLY_MAKE_CONF} " echo "Automatically building a thin image with packages" else echo "Automatically building a * * F A T * * image so we can build ports" fi VARS="MASTER_SITE_BACKUP MASTER_SITE_OVERRIDE PACKAGEROOT PACKAGESITE" for var in $VARS; do val=$(eval echo "\$$var") if [ -n "$val" ]; then CONF_INSTALL="${CONF_INSTALL} $var=$val" fi done typical_embedded ( ) ( # Need to create rc.conf before we copy over /etc to /conf/base/etc # so now's a good time. local rc=${NANO_WORLDDIR}/etc/rc.conf echo "hostname=nanobsd-${NANO_NAME}" > $rc echo "growfs_enable=YES" >> $rc echo "growfs_type=nanobsd-pingpong" >> $rc echo "ntpdate_enable=YES" >> $rc echo "ifconfig_DEFAULT=DHCP" >> $rc echo "ntpdate_hosts='0.freebsd.pool.ntp.org 1.freebsd.pool.ntp.org'" >> $rc # Make sure that firstboot scripts run so growfs works. # Note: still some issues remvoing this XXX touch ${NANO_WORLDDIR}/firstboot ) customize_cmd typical_embedded fix_pkg ( ) ( chdir ${NANO_WORLDDIR} mkdir -p pkg mkdir -p pkg/db mkdir -p pkg/cache mkdir -p pkg/tmp # Needed for pkg bootstrap mkdir -p usr/local/etc # Will get moved to local/etc ( echo 'PKG_DBDIR = "/pkg/db"' echo 'PKG_CACHEDIR = "/pkg/cache"' echo 'DEFAULT_ALWAYS_YES = "yes"' echo 'ASSUME_ALWAYS_YES = "yes"' ) >> usr/local/etc/pkg.conf [ -z ${NANO_NOPRIV_BUILD} ] || ( echo "./pkg type=dir uname=root gname=wheel mode=0755" echo "./pkg/cache type=dir uname=root gname=wheel mode=0755" echo "./pkg/db type=dir uname=root gname=wheel mode=0755" echo "./pkg/tmp type=dir uname=root gname=wheel mode=0755" ) >> ${NANO_METALOG} ) customize_cmd fix_pkg save_build ( ) ( VERSION_FILE=${NANO_WORLDDIR}/etc/version if [ "${SVNREVISION}" = "${REVISION}" ]; then echo "${NANO_NAME}" > "${VERSION_FILE}" else echo "${NANO_NAME} (${SVNREVISION})" > "${VERSION_FILE}" fi ) customize_cmd save_build shrink_md_fbsize ( ) ( # We have a lot of little files on our memory disks. Let's decrease # the block and frag size to fit more little files on them (this # halves our space requirement by ~50% on /etc and /var on 8.x -- # and gives us more back on 9.x as the default block and frag size # are 4 times larger). sed -i '' -e 's,-S -i 4096,-S -i 4096 -b 4096 -f 512,' \ ${NANO_WORLDDIR}/etc/rc.initdiskless ) customize_cmd shrink_md_fbsize customize_cmd cust_comconsole dos_boot_part ( ) ( local d=/usr/local/share/u-boot/${NANO_BOOT_PKG} local f=${NANO_FAT_DIR} # For now, just copy all the files. However, for iMX6 and Allwinner, # we'll need to put a special boot block at a fixed location # on the disk as well. rm -rf $f mkdir $f chdir $f cp ${d}/* . # Also copy ubldr. u-boot will load it and it will load the kernel # from the ufs partition cp ${NANO_WORLDDIR}/boot/ubldr . cp ${NANO_WORLDDIR}/boot/ubldr.bin . # We have to touch the saveenv file touch uEnv.txt # Now we need to copy over dtb files from the build. cp ${NANO_WORLDDIR}/boot/dtb/*.dtb . ) if [ -n "$NANO_BOOT_PKG" ]; then if [ ! -d ${d} ]; then echo ${NANO_BOOT_PKG} not installed. Sadly, it must be. exit 1 fi if [ ! -x /usr/local/bin/mcopy ]; then echo mtools not installed. Sadly, we gotta have it. exit 1 fi customize_cmd dos_boot_part fi product_custom ( ) ( # not quie ready to tweak these in nopriv build if [ -z ${NANO_NOPRIV_BUILD} ]; then # Last second tweaks -- generally not needed chown -R root:wheel ${NANO_WORLDDIR}/root chmod 0755 ${NANO_WORLDDIR}/root/* chmod 0755 ${NANO_WORLDDIR}/* chown -R root:wheel ${NANO_WORLDDIR}/etc chown -R root:wheel ${NANO_WORLDDIR}/boot chown root:wheel ${NANO_WORLDDIR}/ chown root:wheel ${NANO_WORLDDIR}/usr fi ) late_customize_cmd product_custom # # Convenience routines to bring up many settings for standard environments # # # For each architecture, we have a standard set of settings to the extent # it makes sense. For architectures that don't have a standard environment # cfg files need to either define a lot of settings, provide their own disk # imaging, or set which of the variants we support. No subshells, since we # set global variables # std_aarch64 ( ) { } std_amd64 ( ) { std_i386 } std_arm ( ) { } std_armeb ( ) { NANO_ENDIAN=big } std_armv6 ( ) { } std_i386 ( ) { # Default values, if not overridden in .cfg file : ${NANO_KERNEL:=GENERIC} : ${NANO_DRIVE:=ada0} : ${NANO_LAYOUT:=std-x86} : ${NANO_BOOT_MBR:=${NANO_WORLDDIR}/boot/boot0sio} : ${NANO_BOOT_BSD:=${NANO_WORLDDIR}/boot/boot} } std_mips ( ) { NANO_ENDIAN=big } std_mipsel ( ) { } std_mips64 ( ) { NANO_ENDIAN=big } std_mips64el ( ) { } std_powerpc ( ) { NANO_ENDIAN=big } std_powerpc64 ( ) { NANO_LAYOUT=powerpc64-ibm NANO_ENDIAN=big } std_sparc64 ( ) { NANO_ENDIAN=big } # # QEMU settings for the standard environments # qemu_env ( ) { NANO_DISKIMAGE_FORMAT=qcow2 } # other standard environments will go here eval std_${NANO_ARCH} # Slice 1: FAT for ROM loading bootstrap # Slice 2: Config partition # Slice 3: FreeBSD partition (sized exactly) # Slice 4: FreeBSD partition (empty) # on first boot, we resize slice 3 & 4 to be 1/2 of what's # left over on the SD card after slice 1 and 2 are taken # off the top. We also resize the 'a' partion on first boot # to the size of the partition for the ping/pong upgrade. # This feature needs support in the rc.d bootup script. # # Ideally, we'd not put BSD labels on the MBR disks. # However, we can't boot off raw MBR disks. First, # boot2 defaults to 'a' partition, and freaks out # unless you tell it to use 'c'. But even if we # hack that, then /boot/loader wants to load off # of 'c' partition. If you fix that, then we'll # try to mount root, but sanity checks prevent # slices from working. # : ${NANO_ENDIAN:=little} # make -V something to figure it out? : ${NANO_LAYOUT:=std-embedded} : ${NANO_MAKEFS_UFS:=makefs -t ffs -B ${NANO_ENDIAN}} : ${NANO_DISK_SCHEME:=mbr} # No others really supported ATM (well, gpt) case ${NANO_LAYOUT} in std-embedded) NANO_SLICE_FAT=s1 NANO_SLICE_CFG=s2 NANO_SLICE_ROOT=s3 NANO_SLICE_ALTROOT=s4 ;; std-x86) NANO_SLICE_CFG=s1 NANO_SLICE_ROOT=s2 NANO_SLICE_ALTROOT=s3 ;; powerpc64-ibm) NANO_SLICE_PPCBOOT=s1 NANO_SLICE_CFG=s2 NANO_SLICE_ROOT=s3 NANO_SLICE_ALTROOT=s4 ;; powerpc64-apple) echo Not yet exit 1 ;; std-uefi) NANO_SLICE_UEFI=s1 NANO_SLICE_CFG=s2 NANO_SLICE_ROOT=s3 NANO_SLICE_ALTROOT=s4 ;; std-uefi-bios) NANO_DISK_SCHEME=gpt NANO_SLICE_UEFI=p1 NANO_SLICE_BOOT=p2 NANO_SLICE_CFG=p3 NANO_SLICE_ROOT=p4 NANO_SLICE_ALTROOT=p5 # override root name NANO_ROOT=${NANO_SLICE_ROOT} NANO_ALTROOT=${NANO_SLICE_ALTROOT} ;; *) echo Unknown Layout ${NANO_LAYOUT} exit 1 ;; esac NANO_SLICE_DATA= # Not included # Each major disk scheme has its own routine. Generally # this is for mbr, gpt, etc. These are generally are widely # shared, but some specialized formats won't be shared. create_diskimage ( ) ( eval create_diskimage_${NANO_DISK_SCHEME} ) Index: head/tools/tools/shlib-compat/shlib-compat.py =================================================================== --- head/tools/tools/shlib-compat/shlib-compat.py (revision 298880) +++ head/tools/tools/shlib-compat/shlib-compat.py (revision 298881) @@ -1,1157 +1,1157 @@ #!/usr/bin/env python #- # Copyright (c) 2010 Gleb Kurtsou # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ from __future__ import print_function import os import sys import re import optparse class Config(object): version = '0.1' # controlled by user verbose = 0 dump = False no_dump = False version_filter = None symbol_filter = None alias_prefixes = [] # misc opts objdump = 'objdump' dwarfdump = 'dwarfdump' # debug cmpcache_enabled = True dwarfcache_enabled = True w_alias = True w_cached = False w_symbol = True class FileConfig(object): filename = None out = sys.stdout def init(self, outname): if outname and outname != '-': self.out = open(outname, "w") origfile = FileConfig() newfile = FileConfig() exclude_sym_default = [ '^__bss_start$', '^_edata$', '^_end$', '^_fini$', '^_init$', ] @classmethod def init(cls): cls.version_filter = StrFilter() cls.symbol_filter = StrFilter() class App(object): result_code = 0 def warn(cond, msg): if cond: print("WARN: " + msg, file=sys.stderr) # {{{ misc class StrFilter(object): def __init__(self): self.exclude = [] self.include = [] def compile(self): self.re_exclude = [ re.compile(x) for x in self.exclude ] self.re_include = [ re.compile(x) for x in self.include ] def match(self, s): if len(self.re_include): matched = False for r in self.re_include: if r.match(s): matched = True break if not matched: return False for r in self.re_exclude: if r.match(s): return False return True class Cache(object): class CacheStats(object): def __init__(self): self.hit = 0 self.miss = 0 def show(self, name): total = self.hit + self.miss if total == 0: ratio = '(undef)' else: ratio = '%f' % (self.hit/float(total)) return '%s cache stats: hit: %d; miss: %d; ratio: %s' % \ (name, self.hit, self.miss, ratio) def __init__(self, enabled=True, stats=None): self.enabled = enabled self.items = {} if stats == None: self.stats = Cache.CacheStats() else: self.stats = stats def get(self, id): if self.enabled and id in self.items: self.stats.hit += 1 return self.items[id] else: self.stats.miss += 1 return None def put(self, id, obj): if self.enabled: if id in self.items and obj is not self.items[id]: #raise ValueError("Item is already cached: %d (%s, %s)" % # (id, self.items[id], obj)) warn(Config.w_cached, "Item is already cached: %d (%s, %s)" % \ (id, self.items[id], obj)) self.items[id] = obj def replace(self, id, obj): if self.enabled: assert id in self.items self.items[id] = obj class ListDiff(object): def __init__(self, orig, new): self.orig = set(orig) self.new = set(new) self.common = self.orig & self.new self.added = self.new - self.common self.removed = self.orig - self.common class PrettyPrinter(object): def __init__(self): self.stack = [] def run_nested(self, obj): ex = obj._pp_ex(self) self.stack.append(ex) def run(self, obj): self._result = obj._pp(self) return self._result def nested(self): return sorted(set(self.stack)) def result(self): return self._result; # }}} #{{{ symbols and version maps class Symbol(object): def __init__(self, name, offset, version, lib): self.name = name self.offset = offset self.version = version self.lib = lib self.definition = None @property def name_ver(self): return self.name + '@' + self.version def __repr__(self): return "Symbol(%s, 0x%x, %s)" % (self.name, self.offset, self.version) class CommonSymbol(object): def __init__(self, origsym, newsym): if origsym.name != newsym.name or origsym.version != newsym.version: raise RuntimeError("Symbols have different names: %s", [origsym, newsym]) self.origsym = origsym self.newsym = newsym self.name = newsym.name self.version = newsym.version def __repr__(self): return "CommonSymbol(%s, %s)" % (self.name, self.version) class SymbolAlias(object): def __init__(self, alias, prefix, offset): assert alias.startswith(prefix) self.alias = alias self.name = alias[len(prefix):] self.offset = offset def __repr__(self): return "SymbolAlias(%s, 0x%x)" % (self.alias, self.offset) class VersionMap(object): def __init__(self, name): self.name = name self.symbols = {} def append(self, symbol): if (symbol.name in self.symbols): raise ValueError("Symbol is already defined %s@%s" % (symbol.name, self.name)) self.symbols[symbol.name] = symbol def names(self): return self.symbols.keys() def __repr__(self): return repr(self.symbols.values()) # }}} # {{{ types and definitions class Def(object): _is_alias = False def __init__(self, id, name, **kwargs): self.id = id self.name = name self.attrs = kwargs def __getattr__(self, attr): if attr not in self.attrs: raise AttributeError('%s in %s' % (attr, str(self))) return self.attrs[attr] def _name_opt(self, default=''): if not self.name: return default return self.name def _alias(self): if self._is_alias: return self.type._alias() return self def __cmp__(self, other): # TODO assert 'self' and 'other' belong to different libraries #print 'cmp defs: %s, %s' % (self, other) a = self._alias() try: b = other._alias() except AttributeError: return 1 r = cmp(a.__class__, b.__class__) if r == 0: if a.id != 0 and b.id != 0: ind = (long(a.id) << 32) + b.id r = Dwarf.cmpcache.get(ind) if r != None: return r else: ind = 0 r = cmp(a.attrs, b.attrs) if ind != 0: Dwarf.cmpcache.put(ind, r) else: r = 0 #raise RuntimeError('Comparing different classes: %s, %s' % # (a.__class__.__name__, b.__class__.__name__)) return r def __repr__(self): p = [] if hasattr(self, 'name'): p.append("name=%s" % self.name) for (k, v) in self.attrs.items(): if isinstance(v, Def): v = v.__class__.__name__ + '(...)' p.append("%s=%s" % (k, v)) return self.__class__.__name__ + '(' + ', '.join(p) + ')' def _mapval(self, param, vals): if param not in vals.keys(): raise NotImplementedError("Invalid value '%s': %s" % (param, str(self))) return vals[param] def _pp_ex(self, pp): raise NotImplementedError('Extended pretty print not implemeted: %s' % str(self)) def _pp(self, pp): raise NotImplementedError('Pretty print not implemeted: %s' % str(self)) class AnonymousDef(Def): def __init__(self, id, **kwargs): Def.__init__(self, id, None, **kwargs) class Void(AnonymousDef): _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super(Void, cls).__new__( cls, *args, **kwargs) return cls._instance def __init__(self): AnonymousDef.__init__(self, 0) def _pp(self, pp): return "void" class VarArgs(AnonymousDef): def _pp(self, pp): return "..." class PointerDef(AnonymousDef): def _pp(self, pp): t = pp.run(self.type) return "%s*" % (t,) class BaseTypeDef(Def): inttypes = ['DW_ATE_signed', 'DW_ATE_unsigned', 'DW_ATE_unsigned_char'] def _pp(self, pp): if self.encoding in self.inttypes: sign = '' if self.encoding == 'DW_ATE_signed' else 'u' bits = int(self.byte_size, 0) * 8 return '%sint%s_t' % (sign, bits) elif self.encoding == 'DW_ATE_signed_char' and int(self.byte_size, 0) == 1: return 'char'; elif self.encoding == 'DW_ATE_boolean' and int(self.byte_size, 0) == 1: return 'bool'; elif self.encoding == 'DW_ATE_float': return self._mapval(int(self.byte_size, 0), { 16: 'long double', 8: 'double', 4: 'float', }) raise NotImplementedError('Invalid encoding: %s' % self) class TypeAliasDef(Def): _is_alias = True def _pp(self, pp): alias = self._alias() # push typedef name if self.name and not alias.name: alias.name = 'T(%s)' % self.name # return type with modifiers return self.type._pp(pp) class EnumerationTypeDef(Def): def _pp(self, pp): return 'enum ' + self._name_opt('UNKNOWN') class ConstTypeDef(AnonymousDef): _is_alias = True def _pp(self, pp): return 'const ' + self.type._pp(pp) class VolatileTypeDef(AnonymousDef): _is_alias = True def _pp(self, pp): return 'volatile ' + self.type._pp(pp) class RestrictTypeDef(AnonymousDef): _is_alias = True def _pp(self, pp): return 'restrict ' + self.type._pp(pp) class ArrayDef(AnonymousDef): def _pp(self, pp): t = pp.run(self.type) assert len(self.subranges) == 1 try: sz = int(self.subranges[0].upper_bound) + 1 except ValueError: s = re.sub(r'\(.+\)', '', self.subranges[0].upper_bound) sz = int(s) + 1 return '%s[%s]' % (t, sz) class ArraySubrangeDef(AnonymousDef): pass class FunctionDef(Def): def _pp(self, pp): result = pp.run(self.result) if not self.params: params = "void" else: params = ', '.join([ pp.run(x) for x in self.params ]) return "%s %s(%s);" % (result, self.name, params) class FunctionTypeDef(Def): def _pp(self, pp): result = pp.run(self.result) if not self.params: params = "void" else: params = ', '.join([ pp.run(x) for x in self.params ]) return "F(%s, %s, (%s))" % (self._name_opt(), result, params) class ParameterDef(Def): def _pp(self, pp): t = pp.run(self.type) return "%s %s" % (t, self._name_opt()) class VariableDef(Def): def _pp(self, pp): t = pp.run(self.type) return "%s %s" % (t, self._name_opt()) # TODO class StructForwardDef(Def): pass class IncompleteDef(Def): def update(self, complete, cache=None): self.complete = complete complete.incomplete = self if cache != None: cached = cache.get(self.id) if cached != None and isinstance(cached, IncompleteDef): cache.replace(self.id, complete) class StructIncompleteDef(IncompleteDef): def _pp(self, pp): return "struct %s" % (self.name,) class UnionIncompleteDef(IncompleteDef): def _pp(self, pp): return "union %s" % (self.name,) class StructDef(Def): def _pp_ex(self, pp, suffix=';'): members = [ pp.run(x) for x in self.members ] return "struct %s { %s }%s" % \ (self._name_opt(), ' '.join(members), suffix) def _pp(self, pp): if self.name: pp.run_nested(self) return "struct %s" % (self.name,) else: return self._pp_ex(pp, suffix='') class UnionDef(Def): def _pp_ex(self, pp, suffix=';'): members = [ pp.run(x) for x in self.members ] return "union %s { %s }%s" % \ (self._name_opt(), ' '.join(members), suffix) def _pp(self, pp): if self.name: pp.run_nested(self) return "union %s" % (self.name,) else: return self._pp_ex(pp, suffix='') class MemberDef(Def): def _pp(self, pp): t = pp.run(self.type) if self.bit_size: bits = ":%s" % self.bit_size else: bits = "" return "%s %s%s;" % (t, self._name_opt(), bits) class Dwarf(object): cmpcache = Cache(enabled=Config.cmpcache_enabled) def __init__(self, dump): self.dump = dump def _build_optarg_type(self, praw): type = praw.optarg('type', Void()) if type != Void(): type = self.buildref(praw.unit, type) return type def build_subprogram(self, raw): if raw.optname == None: raw.setname('SUBPROGRAM_NONAME_' + raw.arg('low_pc')); params = [ self.build(x) for x in raw.nested ] result = self._build_optarg_type(raw) return FunctionDef(raw.id, raw.name, params=params, result=result) def build_variable(self, raw): type = self._build_optarg_type(raw) return VariableDef(raw.id, raw.optname, type=type) def build_subroutine_type(self, raw): params = [ self.build(x) for x in raw.nested ] result = self._build_optarg_type(raw) return FunctionTypeDef(raw.id, raw.optname, params=params, result=result) def build_formal_parameter(self, raw): type = self._build_optarg_type(raw) return ParameterDef(raw.id, raw.optname, type=type) def build_pointer_type(self, raw): type = self._build_optarg_type(raw) return PointerDef(raw.id, type=type) def build_member(self, raw): type = self.buildref(raw.unit, raw.arg('type')) return MemberDef(raw.id, raw.name, type=type, bit_size=raw.optarg('bit_size', None)) def build_structure_type(self, raw): incomplete = raw.unit.incomplete.get(raw.id) if incomplete == None: incomplete = StructIncompleteDef(raw.id, raw.optname) raw.unit.incomplete.put(raw.id, incomplete) else: return incomplete members = [ self.build(x) for x in raw.nested ] byte_size = raw.optarg('byte_size', None) if byte_size == None: obj = StructForwardDef(raw.id, raw.name, members=members, forcename=raw.name) obj = StructDef(raw.id, raw.optname, members=members, byte_size=byte_size) incomplete.update(obj, cache=raw.unit.cache) return obj def build_union_type(self, raw): incomplete = raw.unit.incomplete.get(raw.id) if incomplete == None: incomplete = UnionIncompleteDef(raw.id, raw.optname) raw.unit.incomplete.put(raw.id, incomplete) else: return incomplete members = [ self.build(x) for x in raw.nested ] byte_size = raw.optarg('byte_size', None) obj = UnionDef(raw.id, raw.optname, members=members, byte_size=byte_size) obj.incomplete = incomplete incomplete.complete = obj return obj def build_typedef(self, raw): type = self._build_optarg_type(raw) return TypeAliasDef(raw.id, raw.name, type=type) def build_const_type(self, raw): type = self._build_optarg_type(raw) return ConstTypeDef(raw.id, type=type) def build_volatile_type(self, raw): type = self._build_optarg_type(raw) return VolatileTypeDef(raw.id, type=type) def build_restrict_type(self, raw): type = self._build_optarg_type(raw) return RestrictTypeDef(raw.id, type=type) def build_enumeration_type(self, raw): # TODO handle DW_TAG_enumerator ??? return EnumerationTypeDef(raw.id, name=raw.optname, byte_size=raw.arg('byte_size')) def build_base_type(self, raw): return BaseTypeDef(raw.id, raw.optname, byte_size=raw.arg('byte_size'), encoding=raw.arg('encoding')) def build_array_type(self, raw): type = self.buildref(raw.unit, raw.arg('type')) subranges = [ self.build(x) for x in raw.nested ] return ArrayDef(raw.id, type=type, subranges=subranges) def build_subrange_type(self, raw): type = self.buildref(raw.unit, raw.arg('type')) return ArraySubrangeDef(raw.id, type=type, upper_bound=raw.optarg('upper_bound', 0)) def build_unspecified_parameters(self, raw): return VarArgs(raw.id) def _get_id(self, id): try: return int(id) except ValueError: if (id.startswith('<') and id.endswith('>')): return int(id[1:-1], 0) else: raise ValueError("Invalid dwarf id: %s" % id) def build(self, raw): obj = raw.unit.cache.get(raw.id) if obj != None: return obj builder_name = raw.tag.replace('DW_TAG_', 'build_') try: builder = getattr(self, builder_name) except AttributeError: raise AttributeError("Unknown dwarf tag: %s" % raw) obj = builder(raw) raw.unit.cache.put(obj.id, obj) return obj def buildref(self, unit, id): id = self._get_id(id) raw = unit.tags[id] obj = self.build(raw) return obj # }}} class Shlib(object): def __init__(self, libfile): self.libfile = libfile self.versions = {} self.alias_syms = {} def parse_objdump(self): objdump = ObjdumpParser(self.libfile) objdump.run() for p in objdump.dynamic_symbols: vername = p['ver'] if vername.startswith('(') and vername.endswith(')'): vername = vername[1:-1] if not Config.version_filter.match(vername): continue if not Config.symbol_filter.match(p['symbol']): continue sym = Symbol(p['symbol'], p['offset'], vername, self) if vername not in self.versions: self.versions[vername] = VersionMap(vername) self.versions[vername].append(sym) if Config.alias_prefixes: self.local_offsetmap = objdump.local_offsetmap for p in objdump.local_symbols: for prefix in Config.alias_prefixes: if not p['symbol'].startswith(prefix): continue alias = SymbolAlias(p['symbol'], prefix, p['offset']) if alias.name in self.alias_syms: prevalias = self.alias_syms[alias.name] if alias.name != prevalias.name or \ alias.offset != prevalias.offset: warn(Config.w_alias, "Symbol alias is " \ "already defined: %s: %s at %08x -- %s at %08x" % \ (alias.alias, alias.name, alias.offset, prevalias.name, prevalias.offset)) self.alias_syms[alias.name] = alias def parse_dwarfdump(self): dwarfdump = DwarfdumpParser(self.libfile) def lookup(sym): raw = None try: raw = dwarfdump.offsetmap[sym.offset] except: try: localnames = self.local_offsetmap[sym.offset] localnames.sort(key=lambda x: -len(x)) for localname in localnames: if localname not in self.alias_syms: continue alias = self.alias_syms[localname] raw = dwarfdump.offsetmap[alias.offset] break except: pass return raw dwarfdump.run() dwarf = Dwarf(dwarfdump) for ver in self.versions.values(): for sym in ver.symbols.values(): raw = lookup(sym); if not raw: warn(Config.w_symbol, "Symbol %s (%s) not found at offset 0x%x" % \ (sym.name_ver, self.libfile, sym.offset)) continue if Config.verbose >= 3: print("Parsing symbol %s (%s)" % (sym.name_ver, self.libfile)) sym.definition = dwarf.build(raw) def parse(self): if not os.path.isfile(self.libfile): print("No such file: %s" % self.libfile, file=sys.stderr) sys.exit(1) self.parse_objdump() self.parse_dwarfdump() # {{{ parsers class Parser(object): def __init__(self, proc): self.proc = proc self.parser = self.parse_begin def run(self): fd = os.popen(self.proc, 'r') while True: line = fd.readline() if (not line): break line = line.strip() if (line): self.parser(line) err = fd.close() if err: print("Execution failed: %s" % self.proc, file=sys.stderr) sys.exit(2) def parse_begin(self, line): print(line) class ObjdumpParser(Parser): re_header = re.compile('(?P\w*)\s*SYMBOL TABLE:') re_local_symbol = re.compile('(?P[0-9a-fA-F]+)\s+(?P\w+)\s+(?P\w+)\s+(?P
[^\s]+)\s+(?P[0-9a-fA-F]+)\s*(?P[^\s]*)') re_lame_symbol = re.compile('(?P[0-9a-fA-F]+)\s+(?P\w+)\s+\*[A-Z]+\*') re_dynamic_symbol = re.compile('(?P[0-9a-fA-F]+)\s+(?P\w+)\s+(?P\w+)\s+(?P
[^\s]+)\s+(?P[0-9a-fA-F]+)\s*(?P[^\s]*)\s*(?P[^\s]*)') def __init__(self, libfile): Parser.__init__(self, "%s -wtT %s" % (Config.objdump, libfile)) self.dynamic_symbols = [] self.local_symbols = [] self.local_offsetmap = {} def parse_begin(self, line): self.parse_header(line) def add_symbol(self, table, symbol, offsetmap = None): offset = int(symbol['offset'], 16); symbol['offset'] = offset if (offset == 0): return table.append(symbol) if offsetmap != None: if offset not in offsetmap: offsetmap[offset] = [symbol['symbol']] else: offsetmap[offset].append(symbol['symbol']) def parse_header(self, line): m = self.re_header.match(line) if (m): table = m.group('table') if (table == "DYNAMIC"): self.parser = self.parse_dynamic elif table == '': self.parser = self.parse_local else: raise ValueError("Invalid symbol table: %s" % table) return True return False def parse_local(self, line): if (self.parse_header(line)): return if (self.re_lame_symbol.match(line)): return m = self.re_local_symbol.match(line) if (not m): return #raise ValueError("Invalid symbol definition: %s" % line) p = m.groupdict() if (p['symbol'] and p['symbol'].find('@') == -1): self.add_symbol(self.local_symbols, p, self.local_offsetmap); def parse_dynamic(self, line): if (self.parse_header(line)): return if (self.re_lame_symbol.match(line)): return m = self.re_dynamic_symbol.match(line) if (not m): raise ValueError("Invalid symbol definition: %s" % line) p = m.groupdict() if (p['symbol'] and p['ver']): self.add_symbol(self.dynamic_symbols, p); class DwarfdumpParser(Parser): tagcache_stats = Cache.CacheStats() class Unit(object): def __init__(self): self.cache = Cache(enabled=Config.dwarfcache_enabled, stats=DwarfdumpParser.tagcache_stats) self.incomplete = Cache() self.tags = {} class Tag(object): def __init__(self, unit, data): self.unit = unit self.id = int(data['id'], 0) self.level = int(data['level']) self.tag = data['tag'] self.args = {} self.nested = [] @property def name(self): return self.arg('name') @property def optname(self): return self.optarg('name', None) def setname(self, name): self.args['DW_AT_name'] = name def arg(self, a): name = 'DW_AT_' + a try: return self.args[name] except KeyError: raise KeyError("Argument '%s' not found in %s: %s" % (name, self, self.args)) def optarg(self, a, default): try: return self.arg(a) except KeyError: return default def __repr__(self): return "Tag(%d, %d, %s)" % (self.level, self.id, self.tag) re_header = re.compile('<(?P\d+)><(?P[0xX0-9a-fA-F]+(?:\+(0[xX])?[0-9a-fA-F]+)?)><(?P\w+)>') re_argname = re.compile('(?P\w+)<') re_argunknown = re.compile('<[^<>]+>') skip_tags = set([ 'DW_TAG_lexical_block', 'DW_TAG_inlined_subroutine', 'DW_TAG_label', 'DW_TAG_variable', ]) external_tags = set([ 'DW_TAG_variable', ]) def __init__(self, libfile): Parser.__init__(self, "%s -di %s" % (Config.dwarfdump, libfile)) self.current_unit = None self.offsetmap = {} self.stack = [] def parse_begin(self, line): if line == '.debug_info': self.parser = self.parse_debuginfo else: raise ValueError("Invalid dwarfdump header: %s" % line) def parse_argvalue(self, args): assert args.startswith('<') i = 1 cnt = 1 while i < len(args) and args[i]: if args[i] == '<': cnt += 1 elif args[i] == '>': cnt -= 1 if cnt == 0: break i = i + 1 value = args[1:i] args = args[i+1:] return (args, value) def parse_arg(self, tag, args): m = self.re_argname.match(args) if not m: m = self.re_argunknown.match(args) if not m: raise ValueError("Invalid dwarfdump: couldn't parse arguments: %s" % args) args = args[len(m.group(0)):].lstrip() return args argname = m.group('arg') args = args[len(argname):] value = [] while len(args) > 0 and args.startswith('<'): (args, v) = self.parse_argvalue(args) value.append(v) args = args.lstrip() if len(value) == 1: value = value[0] tag.args[argname] = value return args def parse_debuginfo(self, line): m = self.re_header.match(line) if not m: raise ValueError("Invalid dwarfdump: %s" % line) if m.group('level') == '0': self.current_unit = DwarfdumpParser.Unit() return tag = DwarfdumpParser.Tag(self.current_unit, m.groupdict()) args = line[len(m.group(0)):].lstrip() while args: args = self.parse_arg(tag, args) tag.unit.tags[tag.id] = tag def parse_offset(tag): if 'DW_AT_low_pc' in tag.args: return int(tag.args['DW_AT_low_pc'], 16) elif 'DW_AT_location' in tag.args: location = tag.args['DW_AT_location'] if location.startswith('DW_OP_addr'): return int(location.replace('DW_OP_addr', ''), 16) return None offset = parse_offset(tag) if offset is not None and \ (tag.tag not in DwarfdumpParser.skip_tags or \ ('DW_AT_external' in tag.args and \ tag.tag in DwarfdumpParser.external_tags)): if offset in self.offsetmap: raise ValueError("Dwarf dump parse error: " + - "symbol is aleady defined at offset 0x%x" % offset) + "symbol is already defined at offset 0x%x" % offset) self.offsetmap[offset] = tag if len(self.stack) > 0: prev = self.stack.pop() while prev.level >= tag.level and len(self.stack) > 0: prev = self.stack.pop() if prev.level < tag.level: assert prev.level == tag.level - 1 # TODO check DW_AT_sibling ??? if tag.tag not in DwarfdumpParser.skip_tags: prev.nested.append(tag) self.stack.append(prev) self.stack.append(tag) assert len(self.stack) == tag.level # }}} def list_str(l): l = [ str(x) for x in l ] l.sort() return ', '.join(l) def names_ver_str(vername, names): return list_str([ x + "@" + vername for x in names ]) def common_symbols(origlib, newlib): result = [] verdiff = ListDiff(origlib.versions.keys(), newlib.versions.keys()) if Config.verbose >= 1: print('Original versions: ', list_str(verdiff.orig)) print('New versions: ', list_str(verdiff.new)) for vername in verdiff.added: print('Added version: ', vername) print(' Added symbols: ', \ names_ver_str(vername, newlib.versions[vername].names())) for vername in verdiff.removed: print('Removed version: ', vername) print(' Removed symbols: ', \ names_ver_str(vername, origlib.versions[vername].names())) added = [] removed = [] for vername in verdiff.common: origver = origlib.versions[vername] newver = newlib.versions[vername] namediff = ListDiff(origver.names(), newver.names()) if namediff.added: added.append(names_ver_str(vername, namediff.added)) if namediff.removed: removed.append(names_ver_str(vername, namediff.removed)) commonver = VersionMap(vername) result.append(commonver) for n in namediff.common: sym = CommonSymbol(origver.symbols[n], newver.symbols[n]) commonver.append(sym) if added: print('Added symbols:') for i in added: print(' ', i) if removed: print('Removed symbols:') for i in removed: print(' ', i) return result def cmp_symbols(commonver): for ver in commonver: names = ver.names(); names.sort() for symname in names: sym = ver.symbols[symname] missing = sym.origsym.definition is None or sym.newsym.definition is None match = not missing and sym.origsym.definition == sym.newsym.definition if not match: App.result_code = 1 if Config.verbose >= 1 or not match: if missing: print('%s: missing definition' % \ (sym.origsym.name_ver,)) continue print('%s: definitions %smatch' % \ (sym.origsym.name_ver, "" if match else "mis")) if Config.dump or (not match and not Config.no_dump): for x in [(sym.origsym, Config.origfile), (sym.newsym, Config.newfile)]: xsym = x[0] xout = x[1].out if not xsym.definition: print('\n// Definition not found: %s %s' % \ (xsym.name_ver, xsym.lib.libfile), file=xout) continue print('\n// Definitions mismatch: %s %s' % \ (xsym.name_ver, xsym.lib.libfile), file=xout) pp = PrettyPrinter() pp.run(xsym.definition) for i in pp.nested(): print(i, file=xout) print(pp.result(), file=xout) def dump_symbols(commonver): class SymbolDump(object): def __init__(self, io_conf): self.io_conf = io_conf self.pp = PrettyPrinter() self.res = [] def run(self, sym): r = self.pp.run(sym.definition) self.res.append('/* %s@%s */ %s' % (sym.name, sym.version, r)) def finish(self): print('\n// Symbol dump: version %s, library %s' % \ (ver.name, self.io_conf.filename), file=self.io_conf.out) for i in self.pp.nested(): print(i, file=self.io_conf.out) print('', file=self.io_conf.out) for i in self.res: print(i, file=self.io_conf.out) for ver in commonver: names = sorted(ver.names()); d_orig = SymbolDump(Config.origfile) d_new = SymbolDump(Config.newfile) for symname in names: sym = ver.symbols[symname] if not sym.origsym.definition or not sym.newsym.definition: # XXX warn(Config.w_symbol, 'Missing symbol definition: %s@%s' % \ (symname, ver.name)) continue d_orig.run(sym.origsym) d_new.run(sym.newsym) d_orig.finish() d_new.finish() if __name__ == '__main__': Config.init() parser = optparse.OptionParser(usage="usage: %prog origlib newlib", version="%prog " + Config.version) parser.add_option('-v', '--verbose', action='count', help="verbose mode, may be specified several times") parser.add_option('--alias-prefix', action='append', help="name prefix to try for symbol alias lookup", metavar="STR") parser.add_option('--dump', action='store_true', help="dump symbol definitions") parser.add_option('--no-dump', action='store_true', help="disable dump for mismatched symbols") parser.add_option('--out-orig', action='store', help="result output file for original library", metavar="ORIGFILE") parser.add_option('--out-new', action='store', help="result output file for new library", metavar="NEWFILE") parser.add_option('--dwarfdump', action='store', help="path to dwarfdump executable", metavar="DWARFDUMP") parser.add_option('--objdump', action='store', help="path to objdump executable", metavar="OBJDUMP") parser.add_option('--exclude-ver', action='append', metavar="RE") parser.add_option('--include-ver', action='append', metavar="RE") parser.add_option('--exclude-sym', action='append', metavar="RE") parser.add_option('--include-sym', action='append', metavar="RE") parser.add_option('--no-exclude-sym-default', action='store_true', help="don't exclude special symbols like _init, _end, __bss_start") for opt in ['alias', 'cached', 'symbol']: parser.add_option("--w-" + opt, action="store_true", dest="w_" + opt) parser.add_option("--w-no-" + opt, action="store_false", dest="w_" + opt) (opts, args) = parser.parse_args() if len(args) != 2: parser.print_help() sys.exit(-1) if opts.dwarfdump: Config.dwarfdump = opts.dwarfdump if opts.objdump: Config.objdump = opts.objdump if opts.out_orig: Config.origfile.init(opts.out_orig) if opts.out_new: Config.newfile.init(opts.out_new) if opts.no_dump: Config.dump = False Config.no_dump = True if opts.dump: Config.dump = True Config.no_dump = False Config.verbose = 1 if opts.verbose: Config.verbose = opts.verbose if opts.alias_prefix: Config.alias_prefixes = opts.alias_prefix Config.alias_prefixes.sort(key=lambda x: -len(x)) for (k, v) in ({ '_sym': Config.symbol_filter, '_ver': Config.version_filter }).items(): for a in [ 'exclude', 'include' ]: opt = getattr(opts, a + k) if opt: getattr(v, a).extend(opt) if not opts.no_exclude_sym_default: Config.symbol_filter.exclude.extend(Config.exclude_sym_default) Config.version_filter.compile() Config.symbol_filter.compile() for w in ['w_alias', 'w_cached', 'w_symbol']: if hasattr(opts, w): v = getattr(opts, w) if v != None: setattr(Config, w, v) (Config.origfile.filename, Config.newfile.filename) = (args[0], args[1]) origlib = Shlib(Config.origfile.filename) origlib.parse() newlib = Shlib(Config.newfile.filename) newlib.parse() commonver = common_symbols(origlib, newlib) if Config.dump: dump_symbols(commonver) cmp_symbols(commonver) if Config.verbose >= 4: print(Dwarf.cmpcache.stats.show('Cmp')) print(DwarfdumpParser.tagcache_stats.show('Dwarf tag')) sys.exit(App.result_code) Index: head/tools/tools/wtap/vis_map/vis_map.c =================================================================== --- head/tools/tools/wtap/vis_map/vis_map.c (revision 298880) +++ head/tools/tools/wtap/vis_map/vis_map.c (revision 298881) @@ -1,117 +1,117 @@ /*- * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ #include #include #include #include /* * From the driver itself */ #include static int dev = -1; static void toggle_medium(int op) { if (ioctl(dev, VISIOCTLOPEN, &op) < 0) { printf("error opening/closing medium\n"); } } static void link_op(struct link *l) { if (ioctl(dev, VISIOCTLLINK, l) < 0) { printf("error making a link operation\n"); } } static void usage(const char *argv[]) { printf("usage: %s [o | c | [ [a|d] wtap_id1 wtap_id2]]\n", argv[0]); } int main(int argc, const char* argv[]) { struct link l; char cmd; if (argc < 2) { usage(argv); exit(1); } dev = open("/dev/visctl", O_RDONLY); if (dev < 0) { printf("error opening visctl cdev\n"); exit(1); } cmd = (char)*argv[1]; switch (cmd) { case 'o': toggle_medium(1); break; case 'c': toggle_medium(0); break; case 'a': if (argc < 4) { usage(argv); exit(1); } l.op = 1; l.id1 = atoi(argv[2]); l.id2 = atoi(argv[3]); link_op(&l); break; case 'd': if (argc < 4) { usage(argv); exit(1); } l.op = 0; l.id1 = atoi(argv[2]); l.id2 = atoi(argv[3]); link_op(&l); break; default: - printf("wtap ioctl: unkown command '%c'\n", *argv[1]); + printf("wtap ioctl: unknown command '%c'\n", *argv[1]); exit(1); } exit(0); } Index: head/tools/tools/wtap/wtap/wtap.c =================================================================== --- head/tools/tools/wtap/wtap/wtap.c (revision 298880) +++ head/tools/tools/wtap/wtap/wtap.c (revision 298881) @@ -1,82 +1,82 @@ /*- * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ #include #include #include #include #include "if_wtapioctl.h" static int dev = -1; static void create(int id) { if(ioctl(dev, WTAPIOCTLCRT, &id) < 0){ printf("error creating wtap with id=%d\n", id); } } static void delete(int id) { if(ioctl(dev, WTAPIOCTLDEL, &id) < 0){ printf("error deleting wtap with id=%d\n", id); } } int main( int argc, const char* argv[]) { if(argc != 3){ printf("usage: %s [c | d] wtap_id\n", argv[0]); return -1; } int id = atoi(argv[2]); if(!(id >= 0 && id < 64)){ printf("wtap_id must be between 0 and 7\n"); return -1; } dev = open("/dev/wtapctl", O_RDONLY); if(dev < 0){ printf("error opening wtapctl cdev\n"); return -1; } switch((char)*argv[1]){ case 'c': create(id); break; case 'd': delete(id); break; default: - printf("wtap ioctl: unkown command '%c'\n", *argv[1]); + printf("wtap ioctl: unknown command '%c'\n", *argv[1]); return -1; } return 0; }