314 lines
7.0 KiB
C
314 lines
7.0 KiB
C
/*
|
|
* Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
|
|
*
|
|
* This document is the property of Apple Inc.
|
|
* It is considered confidential and proprietary.
|
|
*
|
|
* This document may not be reproduced or transmitted in any form,
|
|
* in whole or in part, without the express written permission of
|
|
* Apple Inc.
|
|
*/
|
|
#include <debug.h>
|
|
#include <lib/mib.h>
|
|
#include <list.h>
|
|
#include <lib/libc.h>
|
|
#include <lib/libiboot.h>
|
|
#include <sys/menu.h>
|
|
#include <string.h>
|
|
|
|
static struct mib_node *mib_find_node(u_int32_t oid, bool nofollow);
|
|
|
|
/*
|
|
* Find a node in the MIB.
|
|
*/
|
|
static struct mib_node *
|
|
mib_find_node(u_int32_t oid, bool nofollow)
|
|
{
|
|
void **cursor;
|
|
struct mib_node *node;
|
|
|
|
restart:
|
|
node = NULL;
|
|
|
|
/* Scan the static list for non-weak nodes */
|
|
LINKER_SET_FOREACH(cursor, mib) {
|
|
node = (struct mib_node *)*cursor;
|
|
|
|
if ((oid == node->node_oid) && !(node->node_type & kOIDWeak))
|
|
goto found;
|
|
}
|
|
|
|
/* and finally give weak nodes a chance */
|
|
LINKER_SET_FOREACH(cursor, mib) {
|
|
node = (struct mib_node *)*cursor;
|
|
|
|
if (oid == node->node_oid)
|
|
goto found;
|
|
}
|
|
|
|
// not found
|
|
return NULL;
|
|
|
|
found:
|
|
/* handle indirect nodes */
|
|
if (!nofollow && (NULL != node) && (node->node_type == kOIDTypeOIDIndirect)) {
|
|
oid = node->node_data.v32;
|
|
goto restart;
|
|
}
|
|
return(node);
|
|
}
|
|
|
|
/*
|
|
* Verify whether a node exists or not
|
|
*/
|
|
bool mib_exists(uint32_t oid, void *value)
|
|
{
|
|
bool retVal = false;
|
|
struct mib_node *node;
|
|
if(NULL != (node = mib_find_node(oid, false))) {
|
|
retVal = true;
|
|
if(NULL != value) {
|
|
// value of node has been requested
|
|
switch (node->node_type & kOIDTypeMask) {
|
|
case kOIDTypeUInt32:
|
|
*(u_int32_t *)value = node->node_data.v32;
|
|
break;
|
|
case kOIDTypeInt32:
|
|
*(int32_t *)value = node->node_data.v32;
|
|
break;
|
|
case kOIDTypeUInt64:
|
|
*(u_int64_t *)value = node->node_data.v64;
|
|
break;
|
|
case kOIDTypeInt64:
|
|
*(int64_t *)value = node->node_data.v64;
|
|
break;
|
|
case kOIDTypeBoolean:
|
|
*(bool *)value = node->node_data.v_bool;
|
|
break;
|
|
case kOIDTypeString:
|
|
case kOIDTypeStruct:
|
|
*(void **)value = node->node_data.v_ptr;
|
|
break;
|
|
default:
|
|
panic("unexpected node type 0x%08x for oid 0x%08x", node->node_type, oid);
|
|
}
|
|
}
|
|
}
|
|
return retVal;
|
|
}
|
|
/*
|
|
* Look for a node and return its value if its present.
|
|
*/
|
|
bool
|
|
_mib_find(u_int32_t oid, u_int32_t node_type, void *value)
|
|
{
|
|
struct mib_node *node;
|
|
|
|
/* find the node */
|
|
if (NULL == (node = mib_find_node(oid, false)))
|
|
return(false);
|
|
|
|
/* if we have been given a type hint, check it against the node */
|
|
if ((0 != node_type) && (node_type != (node->node_type & kOIDTypeMask))) {
|
|
panic("MIB node type mismatch: requested 0x%08x actual 0x%08x for oid 0x%08x",
|
|
node_type, node->node_type, oid);
|
|
return(false);
|
|
}
|
|
|
|
if (node->node_type & kOIDFunction) {
|
|
/* call node handler function */
|
|
node->node_data.v_func.func(oid, node->node_data.v_func.arg, value);
|
|
|
|
} else if (node->node_type & kOIDDataIndirect) {
|
|
/* node data is indirected through v_ptr */
|
|
switch (node->node_type & kOIDTypeMask) {
|
|
case kOIDTypeUInt32:
|
|
*(u_int32_t *)value = *(u_int32_t *)node->node_data.v_ptr;
|
|
break;
|
|
case kOIDTypeUInt64:
|
|
*(u_int64_t *)value = *(u_int64_t *)node->node_data.v_ptr;
|
|
break;
|
|
case kOIDTypeBoolean:
|
|
*(bool *)value = *(bool *)node->node_data.v_ptr;
|
|
break;
|
|
case kOIDTypeString:
|
|
case kOIDTypeStruct:
|
|
*(void **)value = *(void **)node->node_data.v_ptr;
|
|
break;
|
|
default:
|
|
panic("unexpected MIB node type 0x%08x for oid 0x%08x", node->node_type, oid);
|
|
}
|
|
|
|
} else {
|
|
/* node data is in the structure */
|
|
switch (node->node_type & kOIDTypeMask) {
|
|
case kOIDTypeUInt32:
|
|
*(u_int32_t *)value = node->node_data.v32;
|
|
break;
|
|
case kOIDTypeInt32:
|
|
*(int32_t *)value = node->node_data.v32;
|
|
break;
|
|
case kOIDTypeUInt64:
|
|
*(u_int64_t *)value = node->node_data.v64;
|
|
break;
|
|
case kOIDTypeInt64:
|
|
*(int64_t *)value = node->node_data.v64;
|
|
break;
|
|
case kOIDTypeBoolean:
|
|
*(bool *)value = node->node_data.v_bool;
|
|
break;
|
|
case kOIDTypeString:
|
|
case kOIDTypeStruct:
|
|
*(void **)value = node->node_data.v_ptr;
|
|
break;
|
|
default:
|
|
panic("unexpected node type 0x%08x for oid 0x%08x", node->node_type, oid);
|
|
}
|
|
}
|
|
return(true);
|
|
}
|
|
|
|
/*
|
|
* Get the value of a node. Panic if it doesn't exist.
|
|
*/
|
|
void
|
|
_mib_get(u_int32_t oid, u_int32_t node_type, void *value)
|
|
{
|
|
if (false == _mib_find(oid, node_type, value))
|
|
panic("mib: oid 0x%08x type 0x%08x not found", oid, node_type);
|
|
}
|
|
|
|
static struct mib_description *
|
|
mib_find_ident(u_int32_t oid)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; mib_desc[i].desc != NULL; i++)
|
|
if (mib_desc[i].oid == oid)
|
|
return(mib_desc + i);
|
|
return(NULL);
|
|
}
|
|
|
|
static void
|
|
mib_find_oid_ident(u_int32_t oid, const char **subsystem, const char **node)
|
|
{
|
|
struct mib_description *md;;
|
|
|
|
*subsystem = "????";
|
|
*node = "????";
|
|
|
|
if (NULL != (md = mib_find_ident(oid & OID_SUBSYSTEM_MASK))) {
|
|
*subsystem = md->desc;
|
|
|
|
if (NULL != (md = mib_find_ident(oid)))
|
|
*node = md->desc;
|
|
}
|
|
}
|
|
|
|
void
|
|
print_mib_node(struct mib_node *node)
|
|
{
|
|
size_t ssize;
|
|
const char *s, *n;
|
|
u_int32_t ntype;
|
|
int cols;
|
|
char f = ' ', i = ' ', w = ' ';
|
|
|
|
mib_find_oid_ident(node->node_oid, &s, &n);
|
|
|
|
if (node->node_type & kOIDDataIndirect) {
|
|
i = 'I';
|
|
}
|
|
|
|
if (node->node_type & kOIDFunction) {
|
|
f = 'F';
|
|
}
|
|
|
|
if (node->node_type & kOIDWeak) {
|
|
w = 'W';
|
|
}
|
|
|
|
printf(" 0x%08x %c%c%c %s.%s ", node->node_oid, f, i, w, s, n);
|
|
cols = strlen(s) + strlen(n) + 16;
|
|
if (cols < 50)
|
|
printf("%*s", 53 - cols, "= ");
|
|
|
|
ntype = node->node_type & kOIDTypeMask;
|
|
|
|
switch (ntype) {
|
|
case kOIDTypeUInt32:
|
|
printf("0x%08x / %u / %d\n",
|
|
mib_get_u32(node->node_oid),
|
|
mib_get_u32(node->node_oid),
|
|
mib_get_u32(node->node_oid));
|
|
break;
|
|
|
|
case kOIDTypeInt32:
|
|
printf("0x%08x / %u / %d\n",
|
|
mib_get_s32(node->node_oid),
|
|
mib_get_s32(node->node_oid),
|
|
mib_get_s32(node->node_oid));
|
|
break;
|
|
|
|
case kOIDTypeUInt64:
|
|
printf("0x%016llx / %llu / %lld\n",
|
|
mib_get_u64(node->node_oid),
|
|
mib_get_u64(node->node_oid),
|
|
mib_get_u64(node->node_oid));
|
|
break;
|
|
|
|
case kOIDTypeInt64:
|
|
printf("0x%016llx / %llu / %lld\n",
|
|
mib_get_s64(node->node_oid),
|
|
mib_get_s64(node->node_oid),
|
|
mib_get_s64(node->node_oid));
|
|
break;
|
|
|
|
case kOIDTypeBoolean:
|
|
printf("%s\n",
|
|
mib_get_bool(node->node_oid) ? "true" : "false");
|
|
break;
|
|
|
|
case kOIDTypeString:
|
|
s = (const char *)mib_get_str(node->node_oid);
|
|
printf("%s\n", s);
|
|
break;
|
|
|
|
case kOIDTypeOIDIndirect:
|
|
printf("-> 0x%08x\n",
|
|
node->node_data.v32);
|
|
break;
|
|
|
|
default:
|
|
if (kOIDTypeStruct == ntype) {
|
|
ssize = node->node_type & kOIDStructSizeMask;
|
|
printf("struct\n");
|
|
if (ssize > 0)
|
|
hexdump(mib_get_ptr(node->node_oid), (ssize <= 128) ? ssize : 128);
|
|
if (ssize > 128)
|
|
printf(" ...\n");
|
|
break;
|
|
}
|
|
printf("unknown type 0x%08x\n", node->node_type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
int
|
|
do_mib(int argc, struct cmd_arg *args)
|
|
{
|
|
void **cursor;
|
|
struct mib_node *node;
|
|
|
|
printf("MIB dump:\n");
|
|
|
|
/* Scan the static list */
|
|
/* XXX note that this will print duplicates for static nodes that are overridden */
|
|
LINKER_SET_FOREACH(cursor, mib) {
|
|
node = (struct mib_node *)*cursor;
|
|
print_mib_node(node);
|
|
}
|
|
return(0);
|
|
}
|
|
|