1 /* ----------------------------------------------------------------------- * 2 * 3 * Copyright 2008 H. Peter Anvin - 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 * ifcpu64.c 15 * 16 * Run one command if the CPU has 64-bit support, and another if it doesn't. 17 * Eventually this and other features should get folded into some kind 18 * of scripting engine. 19 * 20 * Usage: 21 * 22 * label boot_kernel 23 * com32 ifcpu64.c32 24 * append boot_kernel_64 [-- boot_kernel_32pae] -- boot_kernel_32 25 * label boot_kernel_32 26 * kernel vmlinuz_32 27 * append ... 28 * label boot_kernel_64 29 * kernel vmlinuz_64 30 * append ... 31 */ 32 33 #include <alloca.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <cpuid.h> 37 #include <syslinux/boot.h> 38 39 static bool __constfunc cpu_has_cpuid(void) 40 { 41 return cpu_has_eflag(X86_EFLAGS_ID); 42 } 43 44 static bool __constfunc cpu_has_level(uint32_t level) 45 { 46 uint32_t group; 47 uint32_t limit; 48 49 if (!cpu_has_cpuid()) 50 return false; 51 52 group = level & 0xffff0000; 53 limit = cpuid_eax(group); 54 55 if ((limit & 0xffff0000) != group) 56 return false; 57 58 if (level > limit) 59 return false; 60 61 return true; 62 } 63 64 /* This only supports feature groups 0 and 1, corresponding to the 65 Intel and AMD EDX bit vectors. We can add more later if need be. */ 66 static bool __constfunc cpu_has_feature(int x) 67 { 68 uint32_t level = ((x & 1) << 31) | 1; 69 70 return cpu_has_level(level) && ((cpuid_edx(level) >> (x & 31) & 1)); 71 } 72 73 /* XXX: this really should be librarized */ 74 static void boot_args(char **args) 75 { 76 int len = 0, a = 0; 77 char **pp; 78 const char *p; 79 char c, *q, *str; 80 81 for (pp = args; *pp; pp++) 82 len += strlen(*pp) + 1; 83 84 q = str = alloca(len); 85 for (pp = args; *pp; pp++) { 86 p = *pp; 87 while ((c = *p++)) 88 *q++ = c; 89 *q++ = ' '; 90 a = 1; 91 } 92 q -= a; 93 *q = '\0'; 94 95 if (!str[0]) 96 syslinux_run_default(); 97 else 98 syslinux_run_command(str); 99 } 100 101 int main(int argc, char *argv[]) 102 { 103 char **args[3]; 104 int i; 105 int n; 106 107 args[0] = &argv[1]; 108 n = 1; 109 for (i = 1; i < argc; i++) { 110 if (!strcmp(argv[i], "--")) { 111 argv[i] = NULL; 112 args[n++] = &argv[i + 1]; 113 } 114 if (n >= 3) 115 break; 116 } 117 while (n < 3) { 118 args[n] = args[n - 1]; 119 n++; 120 } 121 122 boot_args(cpu_has_feature(X86_FEATURE_LM) ? args[0] : 123 cpu_has_feature(X86_FEATURE_PAE) ? args[1] : args[2]); 124 return -1; 125 } 126