1/* ----------------------------------------------------------------------- * 2 * 3 * Copyright 2009 Erwan Velu - All Rights Reserved 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 8 * Boston MA 02110-1301, USA; either version 2 of the License, or 9 * (at your option) any later version; incorporated herein by reference. 10 * 11 * ----------------------------------------------------------------------- */ 12 13/* 14 * ifcpu.c 15 * 16 */ 17 18#include <alloca.h> 19#include <stdlib.h> 20#include <stdio.h> 21#include <string.h> 22#include <cpuid.h> 23#include <unistd.h> 24#include <syslinux/boot.h> 25#include <com32.h> 26#include <consoles.h> 27 28static inline void error(const char *msg) 29{ 30 fputs(msg, stderr); 31} 32 33static void usage(void) 34{ 35 error("Run one command if system match some CPU features, another if it doesn't. \n" 36 "Usage: \n" 37 " label ifcpu \n" 38 " com32 ifcpu.c32 \n" 39 " append <option> <cpu_features> -- boot_entry_1 -- boot_entry_2 \n" 40 " label boot_entry_1 \n" 41 " kernel vmlinuz_entry1 \n" 42 " append ... \n" 43 " label boot_entry_2 \n" 44 " kernel vmlinuz_entry2 \n" 45 " append ... \n" 46 "\n" 47 "options could be :\n" 48 " debug : display some debugging messages \n" 49 " dry-run : just do the detection, don't boot \n" 50 "\n" 51 "cpu_features could be:\n" 52 " 64 : Processor is x86_64 compatible (lm cpu flag)\n" 53 " hvm : Processor features hardware virtualization (hvm or svm cpu flag)\n" 54 " multicore : Processor must be multi-core \n" 55 " smp : System must be multi-processor \n" 56 " pae : Processor features Physical Address Extension (PAE)\n" 57 " hypervisor : Processor is running under an hypervisor\n" 58 "\n" 59 "if you want to match many cpu features, just separate them with a single space.\n"); 60} 61 62/* XXX: this really should be librarized */ 63static void boot_args(char **args) 64{ 65 int len = 0, a = 0; 66 char **pp; 67 const char *p; 68 char c, *q, *str; 69 70 for (pp = args; *pp; pp++) 71 len += strlen(*pp) + 1; 72 73 q = str = alloca(len); 74 for (pp = args; *pp; pp++) { 75 p = *pp; 76 while ((c = *p++)) 77 *q++ = c; 78 *q++ = ' '; 79 a = 1; 80 } 81 q -= a; 82 *q = '\0'; 83 84 if (!str[0]) 85 syslinux_run_default(); 86 else 87 syslinux_run_command(str); 88} 89 90#define show_bool(mybool) mybool ? "found":"not found" 91 92int main(int argc, char *argv[]) 93{ 94 char **args[3]; 95 int i=0; 96 int n=0; 97 bool hardware_matches = true; 98 bool multicore = false; 99 bool dryrun = false; 100 bool debug = false; 101 102 s_cpu cpu; 103 console_ansi_raw(); 104 detect_cpu(&cpu); 105 106 /* If no argument got passed, let's show the usage */ 107 if (argc == 1) { 108 usage(); 109 return -1; 110 } 111 112 for (i = 1; i < argc; i++) { 113 if (!strcmp(argv[i], "--")) { 114 argv[i] = NULL; 115 args[n++] = &argv[i + 1]; 116 } else if (!strcmp(argv[i], "64")) { 117 if (debug) 118 printf(" 64bit : %s on this system\n", 119 show_bool(cpu.flags.lm)); 120 hardware_matches = cpu.flags.lm && hardware_matches; 121 } else if (!strcmp(argv[i], "pae")) { 122 if (debug) 123 printf(" pae : %s on this system\n", 124 show_bool(cpu.flags.pae)); 125 hardware_matches = cpu.flags.pae && hardware_matches; 126 } else if (!strcmp(argv[i], "hvm")) { 127 if (debug) 128 printf(" hvm : %s on this system\n", 129 show_bool((cpu.flags.vmx || cpu.flags.svm))); 130 hardware_matches = (cpu.flags.vmx || cpu.flags.svm) 131 && hardware_matches; 132 } else if (!strcmp(argv[i], "multicore")) { 133 if (debug) 134 printf(" multicore : %d cores on this system\n", cpu.num_cores); 135 if (cpu.num_cores > 1) 136 multicore = true; 137 hardware_matches = multicore && hardware_matches; 138 } else if (!strcmp(argv[i], "smp")) { 139 if (debug) 140 printf(" smp : %s on this system\n", show_bool(cpu.flags.smp)); 141 hardware_matches = cpu.flags.smp && hardware_matches; 142 } else if (!strcmp(argv[i], "hypervisor")) { 143 if (debug) 144 printf(" hypervisor : %s on this system\n", show_bool(cpu.flags.hypervisor)); 145 hardware_matches = cpu.flags.hypervisor && hardware_matches; 146 } else if (!strcmp(argv[i], "dry-run")) { 147 dryrun = true; 148 } else if (!strcmp(argv[i], "debug")) { 149 debug = true; 150 } 151 if (n >= 2) 152 break; 153 } 154 while (n < 2) { 155 args[n] = args[n - 1]; 156 n++; 157 } 158 if (debug) { 159 printf("\nBooting labels are : '%s' or '%s'\n", *args[0], *args[1]); 160 printf("Hardware requirements%smatch this system, let's booting '%s'\n", 161 hardware_matches ? " " : " doesn't ", 162 hardware_matches ? *args[0] : *args[1]); 163 printf("Sleeping 5sec before booting\n"); 164 if (!dryrun) 165 sleep(5); 166 } 167 168 if (!dryrun) 169 boot_args(hardware_matches ? args[0] : args[1]); 170 else 171 printf("Dry-run mode, let's exiting\n"); 172 173 return -1; 174} 175