/* $Id: kLdrMisc.c 2944 2007-01-13 15:55:40Z bird $ */ /** @file * * kLdr - The Dynamic Loader, Misc APIs. * * Copyright (c) 2006-2007 knut st. osmundsen * * * This file is part of kLdr. * * kLdr is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kLdr is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kLdr; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "kLdr.h" #include "kLdrHlp.h" #include "kLdrInternal.h" /** * Compares arch+cpu some code was generated for with a arch+cpu for executing it * to see if it'll work out fine or not. * * @returns 0 if the code is compatible with the cpu. * @returns KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE if the arch+cpu isn't compatible with the code. * @param enmCodeArch The architecture the code was generated for. * @param enmCodeCpu The cpu the code was generated for. * @param enmArch The architecture to run it on. * @param enmCpu The cpu to run it on. */ int kLdrCompareCpus(KLDRARCH enmCodeArch, KLDRCPU enmCodeCpu, KLDRARCH enmArch, KLDRCPU enmCpu) { /* * Compare arch and cpu. */ if (enmCodeArch != enmArch) return KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; /* exact match is nice. */ if (enmCodeCpu == enmCpu) return 0; switch (enmArch) { case KLDRARCH_X86_16: if (enmCpu < KLDRCPU_FIRST_X86_16 || enmCpu > KLDRCPU_LAST_X86_16) return KLDR_ERR_INVALID_PARAMETER; /* intel? */ if (enmCodeCpu <= KLDRCPU_CORE2_16) { /* also intel? */ if (enmCpu <= KLDRCPU_CORE2_16) return enmCodeCpu <= enmCpu ? 0 : KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; switch (enmCpu) { case KLDRCPU_K6_16: return enmCodeCpu <= KLDRCPU_I586 ? 0 : KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; case KLDRCPU_K7_16: case KLDRCPU_K8_16: default: return enmCodeCpu <= KLDRCPU_I686 ? 0 : KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; } } /* amd */ return enmCpu >= KLDRCPU_K6_16 && enmCpu <= KLDRCPU_K8_16 ? 0 : KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; case KLDRARCH_X86_32: if (enmCpu < KLDRCPU_FIRST_X86_32 || enmCpu > KLDRCPU_LAST_X86_32) return KLDR_ERR_INVALID_PARAMETER; /* blend? */ if (enmCodeCpu == KLDRCPU_X86_32_BLEND) return 0; /* intel? */ if (enmCodeCpu <= KLDRCPU_CORE2_32) { /* also intel? */ if (enmCpu <= KLDRCPU_CORE2_32) return enmCodeCpu <= enmCpu ? 0 : KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; switch (enmCpu) { case KLDRCPU_K6: return enmCodeCpu <= KLDRCPU_I586 ? 0 : KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; case KLDRCPU_K7: case KLDRCPU_K8_32: default: return enmCodeCpu <= KLDRCPU_I686 ? 0 : KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; } } /* amd */ return enmCpu >= KLDRCPU_K6 && enmCpu <= KLDRCPU_K8_32 ? 0 : KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; case KLDRARCH_AMD64: if (enmCpu < KLDRCPU_FIRST_AMD64 || enmCpu > KLDRCPU_LAST_AMD64) return KLDR_ERR_INVALID_PARAMETER; /* blend? */ if (enmCodeCpu == KLDRCPU_AMD64_BLEND) return 0; /* this is simple for now. */ return KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; default: break; } return KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; } /** * Gets the arch+cpu of the calling cpu. * * @param penmArch Where to store the cpu architecture. * @param penmCpu Where to store the cpu brand/model. */ void kLdrGetArchCpu(PKLDRARCH penmArch, PKLDRCPU penmCpu) { #ifdef __AMD64__ *penmArch = KLDRARCH_AMD64; *penmCpu = KLDRCPU_AMD64_BLEND; /** @todo check it using cpu. */ #elif defined(__X86__) *penmArch = KLDRARCH_X86_32; *penmCpu = KLDRCPU_X86_32_BLEND; /** @todo check it using cpu. */ #else # error "Port me" #endif }