星座 网站 建设,wordpress seo 百度,wordpress 用户信息,wordpress界面菜单怎么弄Linux SID 开发指南
1 前言
1.1 编写目的
介绍Linux 内核中基于Sunxi 硬件平台的SID 模块驱动的详细设计#xff0c;为软件编码和维护提供基 础。
1.2 适用范围
内核版本Linux-5.4, Linux-4.9 的平台。
1.3 相关人员
SID 驱动、Efuse 驱动、Sysinfo 驱动的维护、应用开…Linux SID 开发指南
1 前言
1.1 编写目的
介绍Linux 内核中基于Sunxi 硬件平台的SID 模块驱动的详细设计为软件编码和维护提供基 础。
1.2 适用范围
内核版本Linux-5.4, Linux-4.9 的平台。
1.3 相关人员
SID 驱动、Efuse 驱动、Sysinfo 驱动的维护、应用开发人员等。
1.4 术语、定义、缩略语 2 模块描述
2.1 模块功能
SID 提供的功能可以分为四大部分ChipID、SoC Version、Efuse 功能、一些状态位。
2.1.1 Chip ID 功能
对于全志的SoC 来说ChipID 用于该SoC 的唯一标识如A83 的ChipID 标识其在所有A83 中的唯一目前仅保证同一型号SoC 中的ChipID 唯一。ChipID 由4 个word16 个byte组成共128bit通常放在Efuse见2.1.3 节的起始4 个word。具体ChipID 的bit 含义请参考生产制造部为每颗SoC 定义的《ChipID 烧码规则》。
2.1.2 SoC Version 功能
严格讲SoC Version 包含两部分信息 1.Bonding ID表示不同封装。
Version表示改版编号。
说明这两个信息所在的寄存器不一定都在SID 模块内部且各平台位置不一但软件上为了统一管理都归属为SID 模块。
BSP 会返回这两个信息的组合值由应用去判断和做出相应的处理。
2.1.3 Efuse 功能
对软件来说Efuse 中提供了一个可编程的永久存储空间特点是每一位只能写一次从0到1。 Efuse 接口方式Efuse 容量大于512bit 采用SRAM 方式。带有SRAM 的硬件结构示意图如下 2.1.4 一些状态位
Secure Enable标明当前系统的Security 属性是否打开即是否运行了SecureBoot 和SecureOS。 芯片SecureEnable 状态位保存在SID 模块的0xa0 寄存器。
2.2 模块位置
SID 是一个比较独立的模块在Linux 内核中没有依赖其他子系统在Sunxi 平台默认是ko 方式存放在drivers/soc/sunxi 目录中。 SID 为其他模块提供API 的调用方式。关系如下图 1TV、Thermal、GMAC 的校准参数保存在SID 中 2Nand、SMP、VE 需要读取SoC Version 3CE 和HDMI 会用到SID 中的一些Key 4Sysinfo 比较特殊为了方便用户空间获取、调试SID 信息专门设计的一个字符型设 备驱动。
2.3 模块device tree 配置说明(适用Linux-5.4)
SID 模块在Device tree 中通常会用到两个模块的配置信息sunxi-sid 以sun50iw10p1为例需要在sun50iw10p1.dtsi 中添加节点
sid3006000 {
compatible allwinner,sun50iw10p1-sid, allwinner,sunxi-sid;
reg 0x0 0x03006000 0 0x1000;
#address-cells 1;
#size-cells 1;
/* some guys has nothing to do with nvmem */
secure_status {
reg 0x0 0;
offset 0xa0;
size 0x4;
};
chipid {
reg 0x0 0;
offset 0x200;
size 0x10;
};
rotpk {
reg 0x0 0;
offset 0x270;
size 0x20;
};
};在sid 下增加子节点secure_status, chipid, rotpk。就可以用key_info 来访问。
console:/ # echo chipid /sys/class/sunxi_info/key_info ; cat /sys/class/sunxi_info/
key_info
console:/ # 000004002.4 模块源码结构
SID 驱动的源代码目录下
linux-4.9linux-5.4
./drivers/soc/sunxi/
└── sunxi-sid.c // 实现了SID对外的所有API接口对外提供的接口头文件./include/linux/sunxi-sid.h
2.5 内核配置
此配置项一般默认开不需要重新配置 在longan 环境中在根目录执行./build.sh menconfig进入配置主界面配置路径如下
System Type
└─ARM system type
└─Allwinner Ltd. SUNXI family
版配置界面图示 SID 驱动本身没有注册为单独的模块需要通过注册sysinfo 字符驱动实现代码见drivers/char/sunxi-sysinfo/来提供sysfs 节点。 在longan 环境中在根目录执行./build.sh menconfig进入配置主界面配置路径如下
Device Drivers
└─Character devices
└─sunxi system info driver配置界面图示 3 模块设计
3.1 结构框图
SID 驱动内部的功能划分如下图所示 总体上SID 驱动内部可以分为两大部分 1.SID Register RW封装了对寄存器按位读取的接口以及获取指定compatible 的模块基地址等。 2.SID Api以API 的方式提供一些功能接口获取Key、获取SoC Version、获取SecureEnable、获取ChipID 等。
3.2 关键数据定义
3.2.1 常量及宏定义
3.2.1.1 key 的名称定义
在获取Key 的时候调用者需要知道Key 的名称以此作为索引的依据。Key 名称详见sunxisid.h
1 #define EFUSE_CHIPID_NAME chipid
2 #define EFUSE_BROM_CONF_NAME brom_conf
3 #define EFUSE_BROM_TRY_NAME brom_try
4 #define EFUSE_THM_SENSOR_NAME thermal_sensor
5 #define EFUSE_FT_ZONE_NAME ft_zone
6 #define EFUSE_TV_OUT_NAME tvout
7 #define EFUSE_OEM_NAME oem
9 #define EFUSE_WR_PROTECT_NAME write_protect
10 #define EFUSE_RD_PROTECT_NAME read_protect
11 #define EFUSE_IN_NAME in
12 #define EFUSE_ID_NAME id
13 #define EFUSE_ROTPK_NAME rotpk
14 #define EFUSE_SSK_NAME ssk
15 #define EFUSE_RSSK_NAME rssk
16 #define EFUSE_HDCP_HASH_NAME hdcp_hash
17 #define EFUSE_HDCP_PKF_NAME hdcp_pkf
18 #define EFUSE_HDCP_DUK_NAME hdcp_duk
19 #define EFUSE_EK_HASH_NAME ek_hash
20 #define EFUSE_SN_NAME sn
21 #define EFUSE_NV1_NAME nv1
22 #define EFUSE_NV2_NAME nv2
23 #define EFUSE_BACKUP_KEY_NAME backup_key
24 #define EFUSE_RSAKEY_HASH_NAME rsakey_hash
25 #define EFUSE_RENEW_NAME renewability
26 #define EFUSE_OPT_ID_NAME operator_id
27 #define EFUSE_LIFE_CYCLE_NAME life_cycle
28 #define EFUSE_JTAG_SECU_NAME jtag_security
29 #define EFUSE_JTAG_ATTR_NAME jtag_attr
30 #define EFUSE_CHIP_CONF_NAME chip_config
31 #define EFUSE_RESERVED_NAME reserved
32 #define EFUSE_RESERVED2_NAME reserved2
33 /* For KeyLadder */
34 #define EFUSE_KL_SCK0_NAME keyladder_sck0
35 #define EFUSE_KL_KEY0_NAME keyladder_master_key0
36 #define EFUSE_KL_SCK1_NAME keyladder_sck1
37 #define EFUSE_KL_KEY1_NAME keyladder_master_key1sunxi-sid.h 不是所有key 都能访问一般可以访问的已经在dts 定义。
3.2.2 关键数据结构
3.2.2.1 soc_ver_map
用于管理多个SoC 的Version 信息方便用查表的方式实现SoC Version API。其中有两个分量id即BondingIDrev[]用于保存BondingID 和Version 的各种组合值。定义在sunxi-sid.c 中
#define SUNXI_VER_MAX_NUM 8
struct soc_ver_map {
u32 id;
u32 rev[SUNXI_VER_MAX_NUM];
};对于一个SoC 定义一个soc_ver_map 结构数组使用id 和不同Version 在rev[] 中查找对应的组合值。
3.2.2.2 soc_ver_reg
SoC Version、BondingID、SecureEnable 的存储位置因SoC 而异所以定义了一个结构来记录这类信息的位置包括属于那个模块基地址、偏移、掩码、位移等。定义见sunxisid.c
#define SUNXI_SOC_ID_INDEX 1
#define SUNXI_SECURITY_ENABLE_INDEX 2
struct soc_ver_reg {
s8 compatile[48];
u32 offset;
u32 mask;
u32 shift;
};每个SoC 会定义一个soc_ver_reg 数组目前各元素的定义如下 0 - SoC Version 信息在寄存器中的位置。 1 - BondingID 信息在寄存器中的位置。 2 - SecureEnable 信息在寄存器中的位置。
3.2.3 全局变量
定义几个static 全局变量用于保存解析后的ChipID、SoC_Ver 等信息
static unsigned int sunxi_soc_chipid[4];
static unsigned int sunxi_serial[4];
static int sunxi_soc_secure;
static unsigned int sunxi_soc_bin;
static unsigned int sunxi_soc_ver;3.3 模块流程设计
3.3.1 SoC 信息读取流程
本节中这里把SoC Ver、ChipID、SecureEnable 信息统称为“SoC 信息”因为他们的读取过程非常相似。都是遵循以下流程 3.3.2 Efuse Key 读取流程
在读取Efuse 中Key 的时候需要判断是否存在、以及访问权限过程有点复杂用以下流程图进行简单说明。 4 接口设计
4.1 接口函数
4.1.1 s32 sunxi_get_platform(s8 *buf, s32 size)
• 作用获取SoC 平台的名称实际上是一个BSP 研发代号如sun8iw11。 • 参数 • buf: 用于保存平台名称的缓冲区 • size:buf 的大小 • 返回 • 返回buf 中平台名称的实际拷贝长度如果size 小于名称长度返回size。
4.1.2 int sunxi_get_soc_chipid(u8 *chipid)
• 作用获取SoC 的ChipID从Efuse 中读到的原始内容包括数据内容和顺序。 • 参数 • chipid用于保存ChipID 的缓冲区 • 返回 • 会返回0无实际意义
4.1.3 int sunxi_get_serial(u8 *serial)
• 作用获取SoC 的序列号由ChipID 加工而来格式定义见《chipid 接口的实现方案》。 • 参数 • serial用于保存序列号的缓冲区 • 返回 • 会返回0无实际意义
4.1.4 sunxi_get_soc_chipid_str(char *serial)
• 作用获取SoC 的ChipID 的第一个字节要求转换为字符串格式。 • 参数 • serial用于打印ChipID 第一个字节的缓冲区 • 返回 • 只会返回84 个字节的十六进制打印长度无实际意义
4.1.5 int sunxi_get_soc_ft_zone_str(char *serial)
• 作用获取FZ ZONE 的最后一个字节要求转换为字符串格式。 • 参数 • serial用于打印ChipID 第一个字节的缓冲区 • 返回 • 只会返回84 个字节的十六进制打印长度无实际意义
4.1.6 int sunxi_get_soc_rotpk_status_str(char *status)
• 作用获取rotpk 的状态是否烧码 • 参数 • status用于记录是否烧码的缓冲区0未烧1已烧 • 返回 • %d 的长度无实际意义
4.1.7 int sunxi_soc_is_secure(void)
• 作用获取整个系统的Secure 状态即安全系统是否启用。 • 参数 • 无 • 返回 • 0未启用安全系统1启用
4.1.8 unsigned int sunxi_get_soc_bin(void)
• 作用用于芯片分bin部分SoC 平台才支持。 • 参数 • 无 • 返回 • 0: fail • 1: normal • 2: faster • 3: fastest
4.1.9 unsigned int sunxi_get_soc_ver(void)
• 作用获取SoC 的版本信息。 • 参数 • 无 • 返回 • 返回一个十六进制的编号需要调用者去判断版本号然后做出相应的处理。详情参看dts sid 节点。
4.1.10 s32 sunxi_efuse_readn(void key_name, void buf, u32
n) • 作用读取Efuse 中的一个key 信息。 • 参数 • key_name - Key 的名称定义详见sunxi-sid.h • buf - 用于保存Key 值的缓冲区 • size - buf 的大小 • 返回 • 0: success • other: fail 版
4.2 内部函数
4.2.1 static s32 sid_get_base(struct device_node **pnode,
void __iomem **base, s8 *compatible, u32 sec) • 作用从DTS 中获取指定模块的寄存器基地址。 • 参数 • pnode - 用于保存获取到的模块node 信息 • base - 用于保存获取到的寄存器基地址 • compatible - 模块名称用于匹配DTS 中的模块 • 返回 • 0: success • other: fail
4.2.2 static void sid_put_base(struct device_node *pnode,
void __iomem *base, u32 sec) • 作用释放一个模块的基地址。 • 参数 • pnode - 保存模块node 信息 • base - 该模块的寄存器基地址 • 返回 • 无
4.2.3 static u32 sid_rd_bits(s8 *name, u32 offset, u32 shift,
u32 mask, u32 sec) • 作用从一个模块的寄存器中读取指定位置的bit 信息。 • 参数 • name - 模块名称用于匹配DTS 中的模块 • offset - 寄存器相当于基地址的偏移 • shift - 该bit 在寄存器中的位移 • mask - 该bit 的掩码值 • 返回
• 0,fail • other获取到的实际bit 信息 版
5 可测试性
/sys/class/sunxi_info/sys_info 此节点文件可以打印出一些SoC 信息包括版本信息、ChipID 等
# cat /sys/class/sunxi_info/sys_infosunxi_platform : sun50iw10p1
sunxi_secure : secure
sunxi_chipid : 00000000000000000000000000000000
sunxi_chiptype : 00000400
sunxi_batchno : 0x1/sys/class/sunxi_info/key_info 此节点用于获取指定名称的Key 信息。方法是先写入一个Key 名称然后就可以读取到Key 的内容。执行效果如下
# echo chipid /sys/class/sunxi_info/key_info ; cat /sys/class/sunxi_info/key_info
0xf1c1b200: 0x00000400
0xf1c1b204: 0x00000000
0xf1c1b208: 0x00000000
0xf1c1b20c: 0x000000006 其他说明
当启用安全系统后Non-Secure 空间将无法访问大部分的Efuse 信息这个时候需要通过SMC 指令来读取这些Key 信息。此时不能再使用普通的寄存器读接口readl()而是调用的SMC 接口
目前sunxi_smc_readl() 的实现在源代码sunxi-smc.c该文件保存在drivers/char/sunxisysinfo。
int sunxi_smc_readl(phys_addr_t addr)目前sunxi_smc_readl() 的实现在源代码sunxi-smc.c该文件保存在drivers/char/sunxisysinfo。