/* * Copyright (c) 2006 Dell, Inc. * by Matt Domsch * Licensed under the GNU General Public license, version 2. */ #include #include #include #include #include #include #include "libbiosdevname.h" #include "bios_dev_name.h" static struct bios_dev_name_opts opts; int nopirq; int allow_vm; int smver_mjr; int smver_mnr; static void usage(void) { fprintf(stderr, "Usage: biosdevname [options] [args]...\n"); fprintf(stderr, " Options:\n"); fprintf(stderr, " -i or --interface treat [args] as ethernet devs\n"); fprintf(stderr, " --pci-spec treat [args] as PCI specification\n"); fprintf(stderr, " -d or --debug enable debugging\n"); fprintf(stderr, " --policy [physical | all_ethN ]\n"); fprintf(stderr, " --prefix [string] string use for embedded NICs (default='em')\n"); fprintf(stderr, " --smbios [x.y] Require SMBIOS x.y or greater\n"); fprintf(stderr, " --invm Still run in VM\n"); fprintf(stderr, " --nopirq Don't use $PIR table for slot numbers\n"); fprintf(stderr, " Example: biosdevname -i eth0\n"); fprintf(stderr, " returns: em1\n"); fprintf(stderr, " when eth0 is an embedded NIC with label '1' on the chassis.\n"); fprintf(stderr, " You must be root to run this, as it must read from /dev/mem.\n"); } static void conflict(void) { fprintf(stderr, "can't use both interface and pci options\n"); exit(1); } static int set_policy(const char *arg) { int rc = physical; if (!strncmp("physical", arg, sizeof("physical"))) rc = physical; else if (!strncmp("all_ethN", arg, sizeof("all_ethN"))) rc = all_ethN; return rc; } static void parse_opts(int argc, char **argv) { int c; int option_index = 0; while (1) { static struct option long_options[] = /* name, has_arg, flag, val */ { {"debug", no_argument, 0, 'd'}, {"interface", no_argument, 0, 'i'}, {"policy", required_argument, 0, 'p'}, {"prefix", required_argument, 0, 'P'}, {"nopirq", no_argument, 0, 'x'}, {"invm", no_argument, 0, 'V'}, {"smbios", required_argument, 0, 's'}, {"pci-spec", no_argument, 0, 'S'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "dinp:", long_options, &option_index); if (c == -1) break; switch(c) { case 'd': opts.debug = 1; break; case 'i': if (opts.usepci) conflict(); opts.interface = 1; break; case 'S': if (opts.interface) conflict(); opts.usepci = 1; break; case 'p': opts.namingpolicy = set_policy(optarg); break; case 'P': opts.prefix = optarg; break; case 's': sscanf(optarg, "%u.%u", &smver_mjr, &smver_mnr); break; case 'x': nopirq = 1; break; case 'V': allow_vm = 1; break; default: usage(); exit(1); } } if (optind < argc) { opts.argc = argc-optind; opts.argv = &argv[optind]; opts.optind = optind; } if (opts.prefix == NULL) opts.prefix = "em"; } #if defined(__x86_64__) || defined(__i386__) static u_int32_t cpuid (u_int32_t eax, u_int32_t ecx) { asm volatile ( "xor %%ebx, %%ebx; cpuid" : "=a" (eax), "=c" (ecx) : "a" (eax) : "%ebx", "%edx"); return ecx; } /* Algorithm suggested by: http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */ static int running_in_virtual_machine (void) { u_int32_t eax=1U, ecx=0U; ecx = cpuid (eax, ecx); if (ecx & 0x80000000U) return 1; return 0; } #else /* ! __x86_64__ */ static int running_in_virtual_machine (void) { return 1; } #endif static int running_as_root(void) { uid_t uid = geteuid(); if (uid != 0) { fprintf(stderr, "This program must be run as root.\n"); return 0; } return 1; } int main(int argc, char *argv[]) { int i, rc=0; char *name; void *cookie = NULL; parse_opts(argc, argv); if (!running_as_root()) exit(3); if (!allow_vm && running_in_virtual_machine()) exit(4); cookie = setup_bios_devices(opts.namingpolicy, opts.prefix); if (!cookie) { rc = 1; goto out; } if (opts.debug) { unparse_bios_devices(cookie); rc = 0; goto out_cleanup; } if (opts.interface) { for (i=0; i