xref: /qemu/linux-user/uname.c (revision 0effdc29)
118cb0088SRiku Voipio /*
218cb0088SRiku Voipio  *  cpu to uname machine name map
318cb0088SRiku Voipio  *
418cb0088SRiku Voipio  *  Copyright (c) 2009 Loïc Minier
518cb0088SRiku Voipio  *
618cb0088SRiku Voipio  *  This program is free software; you can redistribute it and/or modify
718cb0088SRiku Voipio  *  it under the terms of the GNU General Public License as published by
818cb0088SRiku Voipio  *  the Free Software Foundation; either version 2 of the License, or
918cb0088SRiku Voipio  *  (at your option) any later version.
1018cb0088SRiku Voipio  *
1118cb0088SRiku Voipio  *  This program is distributed in the hope that it will be useful,
1218cb0088SRiku Voipio  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1318cb0088SRiku Voipio  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1418cb0088SRiku Voipio  *  GNU General Public License for more details.
1518cb0088SRiku Voipio  *
1618cb0088SRiku Voipio  *  You should have received a copy of the GNU General Public License
1718cb0088SRiku Voipio  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
1818cb0088SRiku Voipio  */
1918cb0088SRiku Voipio 
20d39594e9SPeter Maydell #include "qemu/osdep.h"
2118cb0088SRiku Voipio 
2218cb0088SRiku Voipio #include "qemu.h"
233b249d26SPeter Maydell #include "user-internals.h"
2418cb0088SRiku Voipio #include "uname.h"
2518cb0088SRiku Voipio 
2618cb0088SRiku Voipio /* return highest utsname machine name for emulated instruction set
2718cb0088SRiku Voipio  *
2818cb0088SRiku Voipio  * NB: the default emulated CPU ("any") might not match any existing CPU, e.g.
2918cb0088SRiku Voipio  * on ARM it has all features turned on, so there is no perfect arch string to
3018cb0088SRiku Voipio  * return here */
cpu_to_uname_machine(CPUArchState * cpu_env)31a0939b89SPhilippe Mathieu-Daudé const char *cpu_to_uname_machine(CPUArchState *cpu_env)
3218cb0088SRiku Voipio {
3318cb0088SRiku Voipio #if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
3418cb0088SRiku Voipio 
3518cb0088SRiku Voipio     /* utsname machine name on linux arm is CPU arch name + endianness, e.g.
3618cb0088SRiku Voipio      * armv7l; to get a list of CPU arch names from the linux source, use:
3718cb0088SRiku Voipio      *     grep arch_name: -A1 linux/arch/arm/mm/proc-*.S
3818cb0088SRiku Voipio      * see arch/arm/kernel/setup.c: setup_processor()
3918cb0088SRiku Voipio      */
4018cb0088SRiku Voipio 
4118cb0088SRiku Voipio     /* in theory, endianness is configurable on some ARM CPUs, but this isn't
4218cb0088SRiku Voipio      * used in user mode emulation */
43ee3eb3a7SMarc-André Lureau #if TARGET_BIG_ENDIAN
4418cb0088SRiku Voipio #define utsname_suffix "b"
4518cb0088SRiku Voipio #else
4618cb0088SRiku Voipio #define utsname_suffix "l"
4718cb0088SRiku Voipio #endif
4818cb0088SRiku Voipio     if (arm_feature(cpu_env, ARM_FEATURE_V7))
4918cb0088SRiku Voipio         return "armv7" utsname_suffix;
5018cb0088SRiku Voipio     if (arm_feature(cpu_env, ARM_FEATURE_V6))
5118cb0088SRiku Voipio         return "armv6" utsname_suffix;
5218cb0088SRiku Voipio     /* earliest emulated CPU is ARMv5TE; qemu can emulate the 1026, but not its
5318cb0088SRiku Voipio      * Jazelle support */
5418cb0088SRiku Voipio     return "armv5te" utsname_suffix;
554d13be8bSPeter Maydell #elif defined(TARGET_I386) && !defined(TARGET_X86_64)
5618cb0088SRiku Voipio     /* see arch/x86/kernel/cpu/bugs.c: check_bugs(), 386, 486, 586, 686 */
570effdc29SPhilippe Mathieu-Daudé     CPUState *cpu = env_cpu(cpu_env);
5818cb0088SRiku Voipio     int family = object_property_get_int(OBJECT(cpu), "family", NULL);
5918cb0088SRiku Voipio     if (family == 4) {
6018cb0088SRiku Voipio         return "i486";
6118cb0088SRiku Voipio     }
6218cb0088SRiku Voipio     if (family == 5) {
6318cb0088SRiku Voipio         return "i586";
6418cb0088SRiku Voipio     }
6518cb0088SRiku Voipio     return "i686";
6618cb0088SRiku Voipio #else
6718cb0088SRiku Voipio     /* default is #define-d in each arch/ subdir */
6818cb0088SRiku Voipio     return UNAME_MACHINE;
6918cb0088SRiku Voipio #endif
7018cb0088SRiku Voipio }
716d30db19SRiku Voipio 
726d30db19SRiku Voipio 
736d30db19SRiku Voipio #define COPY_UTSNAME_FIELD(dest, src) \
746d30db19SRiku Voipio   do { \
75b2acfb55SDaniel P. Berrangé       memcpy((dest), (src), MIN(sizeof(src), sizeof(dest))); \
76b2acfb55SDaniel P. Berrangé       (dest)[sizeof(dest) - 1] = '\0'; \
776d30db19SRiku Voipio   } while (0)
786d30db19SRiku Voipio 
sys_uname(struct new_utsname * buf)796d30db19SRiku Voipio int sys_uname(struct new_utsname *buf)
806d30db19SRiku Voipio {
816d30db19SRiku Voipio   struct utsname uts_buf;
826d30db19SRiku Voipio 
836d30db19SRiku Voipio   if (uname(&uts_buf) < 0)
846d30db19SRiku Voipio       return (-1);
856d30db19SRiku Voipio 
866d30db19SRiku Voipio   /*
876d30db19SRiku Voipio    * Just in case these have some differences, we
886d30db19SRiku Voipio    * translate utsname to new_utsname (which is the
896d30db19SRiku Voipio    * struct linux kernel uses).
906d30db19SRiku Voipio    */
916d30db19SRiku Voipio 
926d30db19SRiku Voipio   memset(buf, 0, sizeof(*buf));
936d30db19SRiku Voipio   COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
946d30db19SRiku Voipio   COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
956d30db19SRiku Voipio   COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
966d30db19SRiku Voipio   COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
976d30db19SRiku Voipio   COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
986d30db19SRiku Voipio #ifdef _GNU_SOURCE
996d30db19SRiku Voipio   COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
1006d30db19SRiku Voipio #endif
1016d30db19SRiku Voipio   return (0);
1026d30db19SRiku Voipio 
1036d30db19SRiku Voipio #undef COPY_UTSNAME_FIELD
1046d30db19SRiku Voipio }
1056d30db19SRiku Voipio 
relstr_to_int(const char * s)1066d30db19SRiku Voipio static int relstr_to_int(const char *s)
1076d30db19SRiku Voipio {
1086d30db19SRiku Voipio     /* Convert a uname release string like "2.6.18" to an integer
1096d30db19SRiku Voipio      * of the form 0x020612. (Beware that 0x020612 is *not* 2.6.12.)
1106d30db19SRiku Voipio      */
1116d30db19SRiku Voipio     int i, n, tmp;
1126d30db19SRiku Voipio 
1136d30db19SRiku Voipio     tmp = 0;
1146d30db19SRiku Voipio     for (i = 0; i < 3; i++) {
1156d30db19SRiku Voipio         n = 0;
1166d30db19SRiku Voipio         while (*s >= '0' && *s <= '9') {
1176d30db19SRiku Voipio             n *= 10;
1186d30db19SRiku Voipio             n += *s - '0';
1196d30db19SRiku Voipio             s++;
1206d30db19SRiku Voipio         }
1216d30db19SRiku Voipio         tmp = (tmp << 8) + n;
1226d30db19SRiku Voipio         if (*s == '.') {
1236d30db19SRiku Voipio             s++;
1246d30db19SRiku Voipio         }
1256d30db19SRiku Voipio     }
1266d30db19SRiku Voipio     return tmp;
1276d30db19SRiku Voipio }
1286d30db19SRiku Voipio 
get_osversion(void)1296d30db19SRiku Voipio int get_osversion(void)
1306d30db19SRiku Voipio {
1316d30db19SRiku Voipio     static int osversion;
1326d30db19SRiku Voipio     struct new_utsname buf;
1336d30db19SRiku Voipio     const char *s;
1346d30db19SRiku Voipio 
1356d30db19SRiku Voipio     if (osversion)
1366d30db19SRiku Voipio         return osversion;
1376d30db19SRiku Voipio     if (qemu_uname_release && *qemu_uname_release) {
1386d30db19SRiku Voipio         s = qemu_uname_release;
1396d30db19SRiku Voipio     } else {
1406d30db19SRiku Voipio         if (sys_uname(&buf))
1416d30db19SRiku Voipio             return 0;
1426d30db19SRiku Voipio         s = buf.release;
1436d30db19SRiku Voipio     }
1446d30db19SRiku Voipio     osversion = relstr_to_int(s);
1456d30db19SRiku Voipio     return osversion;
1466d30db19SRiku Voipio }
1476d30db19SRiku Voipio 
init_qemu_uname_release(void)1486d30db19SRiku Voipio void init_qemu_uname_release(void)
1496d30db19SRiku Voipio {
1506d30db19SRiku Voipio     /* Initialize qemu_uname_release for later use.
1516d30db19SRiku Voipio      * If the host kernel is too old and the user hasn't asked for
1526d30db19SRiku Voipio      * a specific fake version number, we might want to fake a minimum
1536d30db19SRiku Voipio      * target kernel version.
1546d30db19SRiku Voipio      */
1556d30db19SRiku Voipio     struct new_utsname buf;
1566d30db19SRiku Voipio 
1576d30db19SRiku Voipio     if (qemu_uname_release && *qemu_uname_release) {
1586d30db19SRiku Voipio         return;
1596d30db19SRiku Voipio     }
1606d30db19SRiku Voipio 
1616d30db19SRiku Voipio     if (sys_uname(&buf)) {
1626d30db19SRiku Voipio         return;
1636d30db19SRiku Voipio     }
1646d30db19SRiku Voipio 
1656d30db19SRiku Voipio     if (relstr_to_int(buf.release) < relstr_to_int(UNAME_MINIMUM_RELEASE)) {
1666d30db19SRiku Voipio         qemu_uname_release = UNAME_MINIMUM_RELEASE;
1676d30db19SRiku Voipio     }
1686d30db19SRiku Voipio }
169