* - Linux kernel: arch/armX/include/asm/cputype.h
* - GCC sources: config/arch/arch-cores.def
* - Ancient wisdom
+ * - SMBIOS tables (if applicable)
*/
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
#include "lscpu.h"
struct id_part {
{ -1, unknown_part, "unknown" },
};
-void arm_cpu_decode(struct lscpu_desc *desc)
+static void __arm_cpu_decode(struct lscpu_desc *desc)
{
- int j, impl, part;
+ int j, impl = 0;
const struct id_part *parts = NULL;
char *end;
- if (desc->vendor == NULL || desc->model == NULL)
- return;
- if ((strncmp(desc->vendor,"0x",2) != 0 || strncmp(desc->model,"0x",2) ))
- return;
-
- errno = 0;
- impl = (int) strtol(desc->vendor, &end, 0);
- if (errno || desc->vendor == end)
- return;
-
- errno = 0;
- part = (int) strtol(desc->model, &end, 0);
- if (errno || desc->model == end)
- return;
-
- for (j = 0; hw_implementer[j].id != -1; j++) {
- if (hw_implementer[j].id == impl) {
- parts = hw_implementer[j].parts;
- desc->vendor = (char *) hw_implementer[j].name;
- break;
- }
+ if (desc->vendor && startswith(desc->vendor, "0x")) {
+ errno = 0;
+ impl = (int) strtol(desc->vendor, &end, 0);
+ if (errno || desc->vendor == end)
+ return;
}
- if (parts == NULL)
- return;
+ /* model and modelname */
+ if (impl && desc->model && startswith(desc->model, "0x")) {
+ int part;
+
+ errno = 0;
+
+ part = (int) strtol(desc->model, &end, 0);
+ if (errno || desc->model == end)
+ return;
+
+ for (j = 0; hw_implementer[j].id != -1; j++) {
+ if (hw_implementer[j].id == impl) {
+ parts = hw_implementer[j].parts;
+ desc->vendor = (char *) hw_implementer[j].name;
+ break;
+ }
+ }
+
+ if (parts == NULL)
+ return;
- for (j = 0; parts[j].id != -1; j++) {
- if (parts[j].id == part) {
- desc->modelname = (char *) parts[j].name;
- break;
+ for (j = 0; parts[j].id != -1; j++) {
+ if (parts[j].id == part) {
+ desc->modelname = (char *) parts[j].name;
+ break;
+ }
}
}
desc->stepping = xstrdup(buf);
}
}
+
+#define PROC_MFR_OFFSET 0x07
+#define PROC_VERSION_OFFSET 0x10
+
+static int __arm_cpu_smbios(struct lscpu_desc *desc)
+{
+ uint8_t data[8192];
+ char buf[128], *str;
+ struct lscpu_dmi_header h;
+ int fd;
+ ssize_t rs;
+
+ fd = open(_PATH_SYS_DMI_TYPE4, O_RDONLY);
+ if (fd < 0)
+ return fd;
+
+ rs = read_all(fd, (char *) data, 8192);
+ close(fd);
+
+ if (rs == -1)
+ return -1;
+
+ to_dmi_header(&h, data);
+
+ str = dmi_string(&h, data[PROC_MFR_OFFSET]);
+ if (str) {
+ xstrncpy(buf, str, 127);
+ desc->vendor = xstrdup(buf);
+ }
+
+ str = dmi_string(&h, data[PROC_VERSION_OFFSET]);
+ if (str) {
+ xstrncpy(buf, str, 127);
+ desc->modelname = xstrdup(buf);
+ }
+
+ return 0;
+}
+
+void arm_cpu_decode(struct lscpu_desc *desc)
+{
+ int rc = -1;
+
+ /* use SMBIOS Type 4 data if available,
+ * else fall back to manual decoding using the tables above */
+ if (access(_PATH_SYS_DMI_TYPE4, R_OK) == 0)
+ rc = __arm_cpu_smbios(desc);
+
+ if (rc)
+ __arm_cpu_decode(desc);
+}
#include "lscpu.h"
-#define _PATH_SYS_DMI "/sys/firmware/dmi/tables/DMI"
-
#define WORD(x) (uint16_t)(*(const uint16_t *)(x))
#define DWORD(x) (uint32_t)(*(const uint32_t *)(x))
-struct dmi_header
-{
- uint8_t type;
- uint8_t length;
- uint16_t handle;
- uint8_t *data;
-};
-
static void *get_mem_chunk(size_t base, size_t len, const char *devmem)
{
void *p = NULL;
return NULL;
}
-static void to_dmi_header(struct dmi_header *h, uint8_t *data)
-{
- h->type = data[0];
- h->length = data[1];
- memcpy(&h->handle, data + 2, sizeof(h->handle));
- h->data = data;
-}
-
-static char *dmi_string(const struct dmi_header *dm, uint8_t s)
-{
- char *bp = (char *)dm->data;
-
- if (s == 0)
- return NULL;
-
- bp += dm->length;
- while (s > 1 && *bp)
- {
- bp += strlen(bp);
- bp++;
- s--;
- }
-
- if (!*bp)
- return NULL;
-
- return bp;
-}
-
static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
uint16_t num, const char *devmem)
{
/* 4 is the length of an SMBIOS structure header */
while (i < num && data + 4 <= buf + len) {
uint8_t *next;
- struct dmi_header h;
+ struct lscpu_dmi_header h;
to_dmi_header(&h, data);