summaryrefslogtreecommitdiffstats
path: root/sbin/sysctl
diff options
context:
space:
mode:
authorsjg <sjg@FreeBSD.org>2014-11-19 01:07:58 +0000
committersjg <sjg@FreeBSD.org>2014-11-19 01:07:58 +0000
commitb137080f19736ee33fede2e88bb54438604cf86b (patch)
tree377ac0ac449528621eb192cd245adadb5fd53668 /sbin/sysctl
parentab21a29eb607d4dfe389b965fbdee27558e791aa (diff)
parent4a8d07956d121238d006d34ffe7d6269744e8b1a (diff)
downloadFreeBSD-src-b137080f19736ee33fede2e88bb54438604cf86b.zip
FreeBSD-src-b137080f19736ee33fede2e88bb54438604cf86b.tar.gz
Merge from head@274682
Diffstat (limited to 'sbin/sysctl')
-rw-r--r--sbin/sysctl/sysctl.c329
1 files changed, 224 insertions, 105 deletions
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c
index 1359645..a6ea9f9 100644
--- a/sbin/sysctl/sysctl.c
+++ b/sbin/sysctl/sysctl.c
@@ -48,6 +48,16 @@ static const char rcsid[] =
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
+#ifdef __amd64__
+#include <sys/efi.h>
+#include <machine/metadata.h>
+#endif
+
+#if defined(__amd64__) || defined(__i386__)
+#include <machine/pc/bios.h>
+#endif
+
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -69,9 +79,33 @@ static int parsefile(const char *);
static int parse(const char *, int);
static int show_var(int *, int);
static int sysctl_all(int *oid, int len);
-static int name2oid(char *, int *);
+static int name2oid(const char *, int *);
-static int set_IK(const char *, int *);
+static int strIKtoi(const char *, char **);
+
+static int ctl_sign[CTLTYPE+1] = {
+ [CTLTYPE_INT] = 1,
+ [CTLTYPE_LONG] = 1,
+ [CTLTYPE_S64] = 1,
+};
+
+static int ctl_size[CTLTYPE+1] = {
+ [CTLTYPE_INT] = sizeof(int),
+ [CTLTYPE_UINT] = sizeof(u_int),
+ [CTLTYPE_LONG] = sizeof(long),
+ [CTLTYPE_ULONG] = sizeof(u_long),
+ [CTLTYPE_S64] = sizeof(int64_t),
+ [CTLTYPE_U64] = sizeof(uint64_t),
+};
+
+static const char *ctl_typename[CTLTYPE+1] = {
+ [CTLTYPE_INT] = "integer",
+ [CTLTYPE_UINT] = "unsigned integer",
+ [CTLTYPE_LONG] = "long integer",
+ [CTLTYPE_ULONG] = "unsigned long",
+ [CTLTYPE_S64] = "int64_t",
+ [CTLTYPE_U64] = "uint64_t",
+};
static void
usage(void)
@@ -182,7 +216,8 @@ static int
parse(const char *string, int lineno)
{
int len, i, j;
- void *newval = 0;
+ const void *newval;
+ const char *newvalstr = NULL;
int intval;
unsigned int uintval;
long longval;
@@ -191,7 +226,7 @@ parse(const char *string, int lineno)
int64_t i64val;
uint64_t u64val;
int mib[CTL_MAXNAME];
- char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ], line[BUFSIZ];
+ char *cp, *bufp, buf[BUFSIZ], *endptr = NULL, fmt[BUFSIZ], line[BUFSIZ];
u_int kind;
if (lineno)
@@ -221,7 +256,7 @@ parse(const char *string, int lineno)
cp[strlen(cp) - 1] = '\0';
cp++;
}
- newval = cp;
+ newvalstr = cp;
newsize = strlen(cp);
}
len = name2oid(bufp, mib);
@@ -245,7 +280,7 @@ parse(const char *string, int lineno)
exit(1);
}
- if (newval == NULL || dflag) {
+ if (newvalstr == NULL || dflag) {
if ((kind & CTLTYPE) == CTLTYPE_NODE) {
if (dflag) {
i = show_var(mib, len);
@@ -273,97 +308,77 @@ parse(const char *string, int lineno)
return (1);
}
- if ((kind & CTLTYPE) == CTLTYPE_INT ||
- (kind & CTLTYPE) == CTLTYPE_UINT ||
- (kind & CTLTYPE) == CTLTYPE_LONG ||
- (kind & CTLTYPE) == CTLTYPE_ULONG ||
- (kind & CTLTYPE) == CTLTYPE_S64 ||
- (kind & CTLTYPE) == CTLTYPE_U64) {
- if (strlen(newval) == 0) {
+ switch (kind & CTLTYPE) {
+ case CTLTYPE_INT:
+ case CTLTYPE_UINT:
+ case CTLTYPE_LONG:
+ case CTLTYPE_ULONG:
+ case CTLTYPE_S64:
+ case CTLTYPE_U64:
+ if (strlen(newvalstr) == 0) {
warnx("empty numeric value");
return (1);
}
+ /* FALLTHROUGH */
+ case CTLTYPE_STRING:
+ break;
+ default:
+ warnx("oid '%s' is type %d,"
+ " cannot set that%s", bufp,
+ kind & CTLTYPE, line);
+ return (1);
}
+ errno = 0;
+
switch (kind & CTLTYPE) {
case CTLTYPE_INT:
- if (strcmp(fmt, "IK") == 0) {
- if (!set_IK(newval, &intval)) {
- warnx("invalid value '%s'%s",
- (char *)newval, line);
- return (1);
- }
- } else {
- intval = (int)strtol(newval, &endptr,
+ if (strcmp(fmt, "IK") == 0)
+ intval = strIKtoi(newvalstr, &endptr);
+ else
+ intval = (int)strtol(newvalstr, &endptr,
0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid integer '%s'%s",
- (char *)newval, line);
- return (1);
- }
- }
newval = &intval;
newsize = sizeof(intval);
break;
case CTLTYPE_UINT:
- uintval = (int) strtoul(newval, &endptr, 0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid unsigned integer '%s'%s",
- (char *)newval, line);
- return (1);
- }
+ uintval = (int) strtoul(newvalstr, &endptr, 0);
newval = &uintval;
newsize = sizeof(uintval);
break;
case CTLTYPE_LONG:
- longval = strtol(newval, &endptr, 0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid long integer '%s'%s",
- (char *)newval, line);
- return (1);
- }
+ longval = strtol(newvalstr, &endptr, 0);
newval = &longval;
newsize = sizeof(longval);
break;
case CTLTYPE_ULONG:
- ulongval = strtoul(newval, &endptr, 0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid unsigned long integer"
- " '%s'%s", (char *)newval, line);
- return (1);
- }
+ ulongval = strtoul(newvalstr, &endptr, 0);
newval = &ulongval;
newsize = sizeof(ulongval);
break;
case CTLTYPE_STRING:
+ newval = newvalstr;
break;
case CTLTYPE_S64:
- i64val = strtoimax(newval, &endptr, 0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid int64_t '%s'%s",
- (char *)newval, line);
- return (1);
- }
+ i64val = strtoimax(newvalstr, &endptr, 0);
newval = &i64val;
newsize = sizeof(i64val);
break;
case CTLTYPE_U64:
- u64val = strtoumax(newval, &endptr, 0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid uint64_t '%s'%s",
- (char *)newval, line);
- return (1);
- }
+ u64val = strtoumax(newvalstr, &endptr, 0);
newval = &u64val;
newsize = sizeof(u64val);
break;
- case CTLTYPE_OPAQUE:
- /* FALLTHROUGH */
default:
- warnx("oid '%s' is type %d,"
- " cannot set that%s", bufp,
- kind & CTLTYPE, line);
- return (1);
+ /* NOTREACHED */
+ abort();
+ }
+
+ if (errno != 0 || endptr == newvalstr ||
+ (endptr != NULL && *endptr != '\0')) {
+ warnx("invalid %s '%s'%s", ctl_typename[kind & CTLTYPE],
+ newvalstr, line);
+ return (1);
}
i = show_var(mib, len);
@@ -454,12 +469,12 @@ parsefile(const char *filename)
/* These functions will dump out various interesting structures. */
static int
-S_clockinfo(int l2, void *p)
+S_clockinfo(size_t l2, void *p)
{
struct clockinfo *ci = (struct clockinfo*)p;
if (l2 != sizeof(*ci)) {
- warnx("S_clockinfo %d != %zu", l2, sizeof(*ci));
+ warnx("S_clockinfo %zu != %zu", l2, sizeof(*ci));
return (1);
}
printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" :
@@ -469,12 +484,12 @@ S_clockinfo(int l2, void *p)
}
static int
-S_loadavg(int l2, void *p)
+S_loadavg(size_t l2, void *p)
{
struct loadavg *tv = (struct loadavg*)p;
if (l2 != sizeof(*tv)) {
- warnx("S_loadavg %d != %zu", l2, sizeof(*tv));
+ warnx("S_loadavg %zu != %zu", l2, sizeof(*tv));
return (1);
}
printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }",
@@ -485,14 +500,14 @@ S_loadavg(int l2, void *p)
}
static int
-S_timeval(int l2, void *p)
+S_timeval(size_t l2, void *p)
{
struct timeval *tv = (struct timeval*)p;
time_t tv_sec;
char *p1, *p2;
if (l2 != sizeof(*tv)) {
- warnx("S_timeval %d != %zu", l2, sizeof(*tv));
+ warnx("S_timeval %zu != %zu", l2, sizeof(*tv));
return (1);
}
printf(hflag ? "{ sec = %'jd, usec = %'ld } " :
@@ -509,13 +524,13 @@ S_timeval(int l2, void *p)
}
static int
-S_vmtotal(int l2, void *p)
+S_vmtotal(size_t l2, void *p)
{
struct vmtotal *v = (struct vmtotal *)p;
int pageKilo = getpagesize() / 1024;
if (l2 != sizeof(*v)) {
- warnx("S_vmtotal %d != %zu", l2, sizeof(*v));
+ warnx("S_vmtotal %zu != %zu", l2, sizeof(*v));
return (1);
}
@@ -536,36 +551,147 @@ S_vmtotal(int l2, void *p)
v->t_vmshr * pageKilo, v->t_avmshr * pageKilo);
printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n",
v->t_rmshr * pageKilo, v->t_armshr * pageKilo);
- printf("Free Memory:\t%dK\n", v->t_free * pageKilo);
+ printf("Free Memory:\t%dK", v->t_free * pageKilo);
return (0);
}
+#ifdef __amd64__
+#define efi_next_descriptor(ptr, size) \
+ ((struct efi_md *)(((uint8_t *) ptr) + size))
+
static int
-set_IK(const char *str, int *val)
+S_efi_map(size_t l2, void *p)
{
+ struct efi_map_header *efihdr;
+ struct efi_md *map;
+ const char *type;
+ size_t efisz;
+ int ndesc, i;
+
+ static const char *types[] = {
+ "Reserved",
+ "LoaderCode",
+ "LoaderData",
+ "BootServicesCode",
+ "BootServicesData",
+ "RuntimeServicesCode",
+ "RuntimeServicesData",
+ "ConventionalMemory",
+ "UnusableMemory",
+ "ACPIReclaimMemory",
+ "ACPIMemoryNVS",
+ "MemoryMappedIO",
+ "MemoryMappedIOPortSpace",
+ "PalCode"
+ };
+
+ /*
+ * Memory map data provided by UEFI via the GetMemoryMap
+ * Boot Services API.
+ */
+ if (l2 < sizeof(*efihdr)) {
+ warnx("S_efi_map length less than header");
+ return (1);
+ }
+ efihdr = p;
+ efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
+ map = (struct efi_md *)((uint8_t *)efihdr + efisz);
+
+ if (efihdr->descriptor_size == 0)
+ return (0);
+ if (l2 != efisz + efihdr->memory_size) {
+ warnx("S_efi_map length mismatch %zu vs %zu", l2, efisz +
+ efihdr->memory_size);
+ return (1);
+ }
+ ndesc = efihdr->memory_size / efihdr->descriptor_size;
+
+ printf("\n%23s %12s %12s %8s %4s",
+ "Type", "Physical", "Virtual", "#Pages", "Attr");
+
+ for (i = 0; i < ndesc; i++,
+ map = efi_next_descriptor(map, efihdr->descriptor_size)) {
+ if (map->md_type <= EFI_MD_TYPE_PALCODE)
+ type = types[map->md_type];
+ else
+ type = "<INVALID>";
+ printf("\n%23s %012lx %12p %08lx ", type, map->md_phys,
+ map->md_virt, map->md_pages);
+ if (map->md_attr & EFI_MD_ATTR_UC)
+ printf("UC ");
+ if (map->md_attr & EFI_MD_ATTR_WC)
+ printf("WC ");
+ if (map->md_attr & EFI_MD_ATTR_WT)
+ printf("WT ");
+ if (map->md_attr & EFI_MD_ATTR_WB)
+ printf("WB ");
+ if (map->md_attr & EFI_MD_ATTR_UCE)
+ printf("UCE ");
+ if (map->md_attr & EFI_MD_ATTR_WP)
+ printf("WP ");
+ if (map->md_attr & EFI_MD_ATTR_RP)
+ printf("RP ");
+ if (map->md_attr & EFI_MD_ATTR_XP)
+ printf("XP ");
+ if (map->md_attr & EFI_MD_ATTR_RT)
+ printf("RUNTIME");
+ }
+ return (0);
+}
+#endif
+
+#if defined(__amd64__) || defined(__i386__)
+static int
+S_bios_smap_xattr(size_t l2, void *p)
+{
+ struct bios_smap_xattr *smap, *end;
+
+ if (l2 % sizeof(*smap) != 0) {
+ warnx("S_bios_smap_xattr %zu is not a multiple of %zu", l2,
+ sizeof(*smap));
+ return (1);
+ }
+
+ end = (struct bios_smap_xattr *)((char *)p + l2);
+ for (smap = p; smap < end; smap++)
+ printf("\nSMAP type=%02x, xattr=%02x, base=%016jx, len=%016jx",
+ smap->type, smap->xattr, (uintmax_t)smap->base,
+ (uintmax_t)smap->length);
+ return (0);
+}
+#endif
+
+static int
+strIKtoi(const char *str, char **endptrp)
+{
+ int kelv;
float temp;
- int len, kelv;
+ size_t len;
const char *p;
- char *endptr;
- if ((len = strlen(str)) == 0)
- return (0);
+ assert(errno == 0);
+
+ len = strlen(str);
+ /* caller already checked this */
+ assert(len > 0);
+
p = &str[len - 1];
if (*p == 'C' || *p == 'F') {
- temp = strtof(str, &endptr);
- if (endptr == str || endptr != p)
- return (0);
- if (*p == 'F')
- temp = (temp - 32) * 5 / 9;
- kelv = temp * 10 + 2732;
+ temp = strtof(str, endptrp);
+ if (*endptrp != str && *endptrp == p && errno != 0) {
+ if (*p == 'F')
+ temp = (temp - 32) * 5 / 9;
+ return (temp * 10 + 2732);
+ }
} else {
- kelv = (int)strtol(str, &endptr, 10);
- if (endptr == str || *endptr != '\0')
- return (0);
+ kelv = (int)strtol(str, endptrp, 10);
+ if (*endptrp != str && *endptrp == p && errno != 0)
+ return (kelv);
}
- *val = kelv;
- return (1);
+
+ errno = ERANGE;
+ return (0);
}
/*
@@ -578,7 +704,7 @@ set_IK(const char *str, int *val)
*/
static int
-name2oid(char *name, int *oidp)
+name2oid(const char *name, int *oidp)
{
int oid[2];
int i;
@@ -620,21 +746,6 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind)
return (0);
}
-static int ctl_sign[CTLTYPE+1] = {
- [CTLTYPE_INT] = 1,
- [CTLTYPE_LONG] = 1,
- [CTLTYPE_S64] = 1,
-};
-
-static int ctl_size[CTLTYPE+1] = {
- [CTLTYPE_INT] = sizeof(int),
- [CTLTYPE_UINT] = sizeof(u_int),
- [CTLTYPE_LONG] = sizeof(long),
- [CTLTYPE_ULONG] = sizeof(u_long),
- [CTLTYPE_S64] = sizeof(int64_t),
- [CTLTYPE_U64] = sizeof(int64_t),
-};
-
/*
* This formats and outputs the value of one variable
*
@@ -655,7 +766,7 @@ show_var(int *oid, int nlen)
size_t intlen;
size_t j, len;
u_int kind;
- int (*func)(int, void *);
+ int (*func)(size_t, void *);
/* Silence GCC. */
umv = mv = intlen = 0;
@@ -793,6 +904,14 @@ show_var(int *oid, int nlen)
func = S_loadavg;
else if (strcmp(fmt, "S,vmtotal") == 0)
func = S_vmtotal;
+#ifdef __amd64__
+ else if (strcmp(fmt, "S,efi_map_header") == 0)
+ func = S_efi_map;
+#endif
+#if defined(__amd64__) || defined(__i386__)
+ else if (strcmp(fmt, "S,bios_smap_xattr") == 0)
+ func = S_bios_smap_xattr;
+#endif
else
func = NULL;
if (func) {
OpenPOWER on IntegriCloud