4.3.26. boardinfo Debug Guide

4.3.26.1. Overview

The boardinfo driver provides an interface for upper-layer software to obtain board-level information. This document details the functionality of the boardinfo driver and presents two access methods: sysfs and userspace API.

4.3.26.2. Functional Description

The boardinfo driver provides the following main functions:

  • Read key hardware information, including chip model, name, version number, boot method, SOC ID, and DDR information.

  • Configure the BAK slot to be used in the next boot, enabling the system to switch to a specified backup state upon reboot.

With these capabilities, the boardinfo driver delivers real-time and accurate board-level information, ensuring system stability and reliability.

Interface Name Standardization and Userspace API Return Value Tracking Table (X5 Example)

Interface Name Functionality Access Permission Userspace API Result Type Return Value
soc_gen View chip model RO String X5
soc_name View chip name, including sub-models RO String X5M
X5H
UNKNOWN
hw_name View hardware board name RO String x5-fpga
x5-soc
x5-svb
x5-evb
board_version View hardware board version RO String v1
v2
v3
hw_info View full hardware board name
(Composed of <hw_name>-<board_version>-<ddr_vendor>-<ddr_size>-<ddr_freq>)
RO String x5-evb-v2-cxmt-2048MB-4266
...
bootdevice_name View boot method RO String emmc
sd
nand
soc_uid View SOC ID RO String Unique SOC ID
ddr_vendor View DDR manufacturer RO String DDR manufacturer
ddr_type View DDR type, e.g., LPDDR4 or LPDDR4X RO String LPDDR4
LPDDR4X
ddr_freq View maximum DDR frequency, in Mbps RO String 3200 Mbps
3733 Mbps
4266 Mbps
ddr_size View DDR capacity, in MB RO String 1024MB
2048MB
4096MB
8192MB
board_id View hardware board ID RO String Current board_id, printed in hexadecimal
sec_chip View whether it is a secure chip RO String Chip without key burned: nosec_chip
Chip with Gua key burned: sec_chip1
Chip with customer's public key hash burned: sec_chip2
sec_boot View whether AVB and dm-verity verification are enabled RO String enable
disable
bak_slot Read: currently active BAK slot;
Write: set BAK slot for next boot
R/W String 0
1

For instructions on burning customer’s own public key hash, refer to X5 Customer Root RSA Key Hash Burning and Usage

4.3.26.3. Driver Code

The socinfo driver code is located at kernel/drivers/soc/hobot/socinfo/socinfo.c, with the following main functionalities:

  • Read board-level information configured in the DTS configuration file and store it into corresponding variables.

	if (read_from_property(pdev, "soc_gen", &soc_gen) ||
		read_from_property(pdev, "soc_name", &soc_name) ||
		read_from_property(pdev, "hw_name", &hw_name) ||
		read_from_property(pdev, "board_version", &board_version) ||
		read_from_property(pdev, "hw_info", &hw_info) ||
		read_from_property(pdev, "bootdevice_name", &bootdevice_name) ||
		read_from_property(pdev, "soc_uid", &soc_uid) ||
		read_from_property(pdev, "board_id", &board_id) ||
		read_from_property(pdev, "sec_chip", &sec_chip) ||
		read_from_property(pdev, "sec_boot", &sec_boot)) {
		return -1;
	}
  • Implement sysfs interface to provide upper-layer software with access to board-level information.

static struct class_attribute soc_gen_attribute =
	__ATTR(soc_gen, 0444, soc_gen_show, NULL);

static struct class_attribute soc_name_attribute =
	__ATTR(soc_name, 0444, soc_name_show, NULL);

static struct class_attribute hw_name_attribute =
	__ATTR(hw_name, 0444, hw_name_show, NULL);

static struct class_attribute board_version_attribute =
	__ATTR(board_version, 0444, board_version_show, NULL);

static struct class_attribute hw_info_attribute =
	__ATTR(hw_info, 0444, hw_info_show, NULL);

static struct class_attribute bootdevice_name_attribute =
	__ATTR(bootdevice_name, 0444, bootdevice_name_show, NULL);

static struct class_attribute soc_uid_attribute =
	__ATTR(soc_uid, 0444, soc_uid_show, NULL);

static struct class_attribute ddr_vender_attribute =
	__ATTR(ddr_vendor, 0444, ddr_vender_show, NULL);

static struct class_attribute ddr_type_attribute =
	__ATTR(ddr_type, 0444, ddr_type_show, NULL);

static struct class_attribute ddr_freq_attribute =
	__ATTR(ddr_freq, 0444, ddr_freq_show, NULL);

static struct class_attribute ddr_size_attribute =
	__ATTR(ddr_size, 0444, ddr_size_show, NULL);

static struct class_attribute board_id_attribute =
	__ATTR(board_id, 0444, board_id_show, NULL);

static struct class_attribute sec_chip_attribute =
	__ATTR(sec_chip, 0444, sec_chip_show, NULL);

static struct class_attribute sec_boot_attribute =
	__ATTR(sec_boot, 0444, sec_boot_show, NULL);

static struct class_attribute bak_slot_attribute =
	__ATTR(bak_slot, 0644, bak_slot_show, bak_slot_store);

“soc_gen” and “soc_name” must be configured in the Kernel DTS file, located at kernel/arch/arm64/boot/dts/hobot/x5.dtsi, under the node named “socinfo”.

Currently, in the kernel DTS, the placeholder length for "hw_name" and "board_version" is 16 bytes, and for "hw_info" it is 32 bytes. If any field exceeds its placeholder length, the socinfo driver initialization will fail.

kernel_dts.png

Information such as “board_id”, “hw_name”, and “board_version” must be configured in the Uboot DTS file, located at uboot/arch/arm/dts/x5.dtsi, under the node named “board_type”.
The board_type_array field in DTS corresponds to “board_id”; refer to Modify Board ID Macro Definitions for related changes.
The hardward_array field corresponds to “hw_name”, and the board_version field corresponds to “board_version”.

uboot_dts1.png

4.3.26.4. Usage

sysfs Interface

The sysfs interface path is /sys/class/socinfo/, currently supporting retrieval of the following information:

For example, to view board-level interface information, execute the following commands in the terminal:

# View chip model
root@buildroot:~# cat /sys/class/socinfo/soc_gen
x5

# View chip name
root@buildroot:~# cat /sys/class/socinfo/soc_name
X5M

# View hardware board name
root@buildroot:~# cat /sys/class/socinfo/hw_name
X5_EVB_LP4

# View hardware board version
root@buildroot:~# cat /sys/class/socinfo/board_version
1_B

# View full hardware board name
root@buildroot:~# cat /sys/class/socinfo/hw_info
X5_EVB_LP4_1_B_cxmt_4096MB_4266

# View boot method
root@buildroot:~# cat /sys/class/socinfo/bootdevice_name
emmc

# View SOC ID
root@buildroot:~# cat /sys/class/socinfo/soc_uid
0x308064960e31499301f0822400000000

# View DDR manufacturer
root@buildroot:~# cat /sys/class/socinfo/ddr_vendor
cxmt

# View DDR type
root@buildroot:~# cat /sys/class/socinfo/ddr_type
LPDDR4

# View maximum DDR frequency
root@buildroot:~# cat /sys/class/socinfo/ddr_freq
4266 Mbps

# View DDR capacity
root@buildroot:~# cat /sys/class/socinfo/ddr_size
4096MB

# View hardware board ID
root@buildroot:~# cat /sys/class/socinfo/board_id
0x0202

# View chip secure type
root@buildroot:~# cat /sys/class/socinfo/sec_chip
sec_chip1

# View whether secure boot is enabled
root@buildroot:~# cat /sys/class/socinfo/sec_boot
enable

# View current active BAK slot
root@buildroot:~# cat /sys/class/socinfo/bak_slot
0
# Set BAK slot for next boot
root@buildroot:~# echo 1 > /sys/class/socinfo/bak_slot
root@buildroot:~# reboot
root@buildroot:~# cat /sys/class/socinfo/bak_slot
1

Note: If the chip name soc_name is UNKNOWN, it indicates an early production chip that has not had the corresponding bit written in eFUSE; the chip type must then be identified by its silkscreen marking.

hw_info is composed of <hw_name>-<board_version>-<ddr_vendor>-<ddr_size>-<ddr_freq>:

  • hw_name: X5_EVB_LP4

  • board_version: 1_B

  • ddr_vendor: cxmt

  • ddr_size: 4096MB

  • ddr_freq: 4266

Userspace API Interface

Source path: hbre/hbutils/boardinfo

Header file: boardinfo.h

Library: libboardinfo.so.1

Interface Definition

hb_get_boardinfo

【Function Declaration】

int32_t hb_get_boardinfo(char *key, void *dst, uint32_t len);

【Parameter Description】

  • [OUT] key: The board-level information to retrieve

  • [OUT] dst: Buffer to store the result

  • [IN] len: Maximum buffer size

【Return Value】

  • HB_BINFO_SUCCESS: Success

  • HB_BINFO_INVALID_PARAM: Invalid parameter (e.g., null pointer)

  • HB_BINFO_SHORT_BUF: Buffer too small

  • HB_BINFO_PLAT_NOT_SUPPORT: Board information not supported on this platform

【Functionality】

Retrieves board-level information specified by key, stores the result in dst, and returns an error code.

Error Types Returned by Dynamic Library Interface

Error values defined in the dynamic library:

enum hb_binfo_retval {
	HB_BINFO_SUCCESS,
	HB_BINFO_INVALID_PARAM,
	HB_BINFO_SHORT_BUF,
	HB_BINFO_PLAT_NOT_SUPPORT,
};

Example Code

When calling the userspace API, link the dynamic library first. Example code:

#include <stdio.h>
#include <stdint.h>
#include "boardinfo.h"

int main(void) {
	int32_t ret;
	char buf[1024];

	ret = hb_get_boardinfo("soc_gen", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("soc_gen:%s\n", buf);
	}

	ret = hb_get_boardinfo("soc_name", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("soc_name:%s\n", buf);
	}

	ret = hb_get_boardinfo("hw_name", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("hw_name:%s\n", buf);
	}

	ret = hb_get_boardinfo("board_version", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("board_version:%s\n", buf);
	}

	ret = hb_get_boardinfo("hw_info", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("hw_info:%s\n", buf);
	}

	ret = hb_get_boardinfo("bootdevice_name", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("bootdevice_name:%s\n", buf);
	}

	ret = hb_get_boardinfo("soc_uid", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("soc_uid:%s\n", buf);
	}

	ret = hb_get_boardinfo("ddr_type", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("ddr_type:%s\n", buf);
	}

	ret = hb_get_boardinfo("ddr_size", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("ddr_size:%s\n", buf);
	}

	ret = hb_get_boardinfo("ddr_vendor", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("ddr_vendor:%s\n", buf);
	}

	ret = hb_get_boardinfo("ddr_freq", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("ddr_freq:%s\n", buf);
	}

	ret = hb_get_boardinfo("board_id", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("board_id:%s\n", buf);
	}

	ret = hb_get_boardinfo("sec_chip", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("sec_chip:%s\n", buf);
	}

	ret = hb_get_boardinfo("sec_boot", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("sec_boot:%s\n", buf);
	}

	ret = hb_get_boardinfo("board_id", buf, 2);
	if (ret == 0) {
		printf("hb_get_boardinfo test HB_BINFO_SHORT_BUF failed\n");
	} else {
		printf("hb_get_boardinfo test HB_BINFO_SHORT_BUF pass\n");
	}

	ret = hb_get_boardinfo("bak_slot", buf, 1024);
	if (ret) {
		printf("hb_get_boardinfo failed, ret:%d\n", ret);
	} else {
		printf("bak_slot:%s\n", buf);
	}

	ret = hb_get_boardinfo(NULL, buf, 1024);
	if (ret == 0) {
		printf("hb_get_boardinfo test HB_BINFO_INVALID_PARAM failed\n");
	} else {
		printf("hb_get_boardinfo test HB_BINFO_INVALID_PARAM pass\n");
	}

	ret = hb_get_boardinfo("xx", buf, 1024);
	if (ret == 0) {
		printf("hb_get_boardinfo test HB_BINFO_INVALID_PARAM failed\n");
	} else {
		printf("hb_get_boardinfo test HB_BINFO_INVALID_PARAM pass\n");
	}

	return 0;
}

4.3.26.5. Common Issues

  • When using the userspace API, if the provided key does not exist, the function returns the error HB_BINFO_INVALID_PARAM. In this case, the dst pointer remains unmodified; always check whether the return value is 0.