1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <sys/utsname.h>
4 
5 #include "architecture.h"
6 #include "macro.h"
7 #include "string-table.h"
8 #include "string-util.h"
9 
uname_architecture(void)10 Architecture uname_architecture(void) {
11 
12         /* Return a sanitized enum identifying the architecture we are running on. This
13          * is based on uname(), and the user may hence control what this returns by using
14          * personality(). This puts the user in control on systems that can run binaries
15          * of multiple architectures.
16          *
17          * We do not translate the string returned by uname() 1:1. Instead we try to
18          * clean it up and break down the confusion on x86 and arm in particular.
19          *
20          * We try to distinguish CPUs, not CPU features, i.e. actual architectures that
21          * have genuinely different code. */
22 
23         static const struct {
24                 const char *machine;
25                 Architecture arch;
26         } arch_map[] = {
27 #if defined(__aarch64__) || defined(__arm__)
28                 { "aarch64",    ARCHITECTURE_ARM64    },
29                 { "aarch64_be", ARCHITECTURE_ARM64_BE },
30                 { "armv8l",     ARCHITECTURE_ARM      },
31                 { "armv8b",     ARCHITECTURE_ARM_BE   },
32                 { "armv7ml",    ARCHITECTURE_ARM      },
33                 { "armv7mb",    ARCHITECTURE_ARM_BE   },
34                 { "armv7l",     ARCHITECTURE_ARM      },
35                 { "armv7b",     ARCHITECTURE_ARM_BE   },
36                 { "armv6l",     ARCHITECTURE_ARM      },
37                 { "armv6b",     ARCHITECTURE_ARM_BE   },
38                 { "armv5tl",    ARCHITECTURE_ARM      },
39                 { "armv5tel",   ARCHITECTURE_ARM      },
40                 { "armv5tejl",  ARCHITECTURE_ARM      },
41                 { "armv5tejb",  ARCHITECTURE_ARM_BE   },
42                 { "armv5teb",   ARCHITECTURE_ARM_BE   },
43                 { "armv5tb",    ARCHITECTURE_ARM_BE   },
44                 { "armv4tl",    ARCHITECTURE_ARM      },
45                 { "armv4tb",    ARCHITECTURE_ARM_BE   },
46                 { "armv4l",     ARCHITECTURE_ARM      },
47                 { "armv4b",     ARCHITECTURE_ARM_BE   },
48 
49 #elif defined(__alpha__)
50                 { "alpha" ,     ARCHITECTURE_ALPHA    },
51 
52 #elif defined(__arc__)
53                 { "arc",        ARCHITECTURE_ARC      },
54                 { "arceb",      ARCHITECTURE_ARC_BE   },
55 
56 #elif defined(__cris__)
57                 { "crisv32",    ARCHITECTURE_CRIS     },
58 
59 #elif defined(__i386__) || defined(__x86_64__)
60                 { "x86_64",     ARCHITECTURE_X86_64   },
61                 { "i686",       ARCHITECTURE_X86      },
62                 { "i586",       ARCHITECTURE_X86      },
63                 { "i486",       ARCHITECTURE_X86      },
64                 { "i386",       ARCHITECTURE_X86      },
65 
66 #elif defined(__ia64__)
67                 { "ia64",       ARCHITECTURE_IA64     },
68 
69 #elif defined(__hppa__) || defined(__hppa64__)
70                 { "parisc64",   ARCHITECTURE_PARISC64 },
71                 { "parisc",     ARCHITECTURE_PARISC   },
72 
73 #elif defined(__loongarch64)
74                 { "loongarch64", ARCHITECTURE_LOONGARCH64 },
75 
76 #elif defined(__m68k__)
77                 { "m68k",       ARCHITECTURE_M68K     },
78 
79 #elif defined(__mips__) || defined(__mips64__)
80                 { "mips64",     ARCHITECTURE_MIPS64   },
81                 { "mips",       ARCHITECTURE_MIPS     },
82 
83 #elif defined(__nios2__)
84                 { "nios2",      ARCHITECTURE_NIOS2    },
85 
86 #elif defined(__powerpc__) || defined(__powerpc64__)
87                 { "ppc64le",    ARCHITECTURE_PPC64_LE },
88                 { "ppc64",      ARCHITECTURE_PPC64    },
89                 { "ppcle",      ARCHITECTURE_PPC_LE   },
90                 { "ppc",        ARCHITECTURE_PPC      },
91 
92 #elif defined(__riscv)
93                 { "riscv64",    ARCHITECTURE_RISCV64  },
94                 { "riscv32",    ARCHITECTURE_RISCV32  },
95 #  if __SIZEOF_POINTER__ == 4
96                 { "riscv",      ARCHITECTURE_RISCV32  },
97 #  elif __SIZEOF_POINTER__ == 8
98                 { "riscv",      ARCHITECTURE_RISCV64  },
99 #  endif
100 
101 #elif defined(__s390__) || defined(__s390x__)
102                 { "s390x",      ARCHITECTURE_S390X    },
103                 { "s390",       ARCHITECTURE_S390     },
104 
105 #elif defined(__sh__) || defined(__sh64__)
106                 { "sh5",        ARCHITECTURE_SH64     },
107                 { "sh4a",       ARCHITECTURE_SH       },
108                 { "sh4",        ARCHITECTURE_SH       },
109                 { "sh3",        ARCHITECTURE_SH       },
110                 { "sh2a",       ARCHITECTURE_SH       },
111                 { "sh2",        ARCHITECTURE_SH       },
112 
113 #elif defined(__sparc__)
114                 { "sparc64",    ARCHITECTURE_SPARC64  },
115                 { "sparc",      ARCHITECTURE_SPARC    },
116 
117 #elif defined(__tilegx__)
118                 { "tilegx",     ARCHITECTURE_TILEGX   },
119 
120 #else
121 #  error "Please register your architecture here!"
122 #endif
123         };
124 
125         static Architecture cached = _ARCHITECTURE_INVALID;
126         struct utsname u;
127 
128         if (cached != _ARCHITECTURE_INVALID)
129                 return cached;
130 
131         assert_se(uname(&u) >= 0);
132 
133         for (size_t i = 0; i < ELEMENTSOF(arch_map); i++)
134                 if (streq(arch_map[i].machine, u.machine))
135                         return cached = arch_map[i].arch;
136 
137         assert_not_reached();
138         return _ARCHITECTURE_INVALID;
139 }
140 
141 /* Maintain same order as in the table above. */
142 static const char *const architecture_table[_ARCHITECTURE_MAX] = {
143         [ARCHITECTURE_ARM64]       = "arm64",
144         [ARCHITECTURE_ARM64_BE]    = "arm64-be",
145         [ARCHITECTURE_ARM]         = "arm",
146         [ARCHITECTURE_ARM_BE]      = "arm-be",
147         [ARCHITECTURE_ALPHA]       = "alpha",
148         [ARCHITECTURE_ARC]         = "arc",
149         [ARCHITECTURE_ARC_BE]      = "arc-be",
150         [ARCHITECTURE_CRIS]        = "cris",
151         [ARCHITECTURE_X86_64]      = "x86-64",
152         [ARCHITECTURE_X86]         = "x86",
153         [ARCHITECTURE_IA64]        = "ia64",
154         [ARCHITECTURE_LOONGARCH64] = "loongarch64",
155         [ARCHITECTURE_M68K]        = "m68k",
156         [ARCHITECTURE_MIPS64_LE]   = "mips64-le",
157         [ARCHITECTURE_MIPS64]      = "mips64",
158         [ARCHITECTURE_MIPS_LE]     = "mips-le",
159         [ARCHITECTURE_MIPS]        = "mips",
160         [ARCHITECTURE_NIOS2]       = "nios2",
161         [ARCHITECTURE_PARISC64]    = "parisc64",
162         [ARCHITECTURE_PARISC]      = "parisc",
163         [ARCHITECTURE_PPC64_LE]    = "ppc64-le",
164         [ARCHITECTURE_PPC64]       = "ppc64",
165         [ARCHITECTURE_PPC]         = "ppc",
166         [ARCHITECTURE_PPC_LE]      = "ppc-le",
167         [ARCHITECTURE_RISCV32]     = "riscv32",
168         [ARCHITECTURE_RISCV64]     = "riscv64",
169         [ARCHITECTURE_S390X]       = "s390x",
170         [ARCHITECTURE_S390]        = "s390",
171         [ARCHITECTURE_SH64]        = "sh64",
172         [ARCHITECTURE_SH]          = "sh",
173         [ARCHITECTURE_SPARC64]     = "sparc64",
174         [ARCHITECTURE_SPARC]       = "sparc",
175         [ARCHITECTURE_TILEGX]      = "tilegx",
176 };
177 
178 DEFINE_STRING_TABLE_LOOKUP(architecture, Architecture);
179