OpenBMC在版本2.2之后出于安全考虑禁用了/dev/mem,从内核角度来看,是从4.13之后开始禁用的。在禁用/dev/mem之后,devmem工具将处于不可用状态,对于内核开发者来说,这是一个令人沮丧的决定。当然,有一些开发者也表达了对这一决定的反对,但官方开发组毅然决然的禁用了/dev/mem。值得庆幸的是,官方开发组为开发者留下了一个“开关”用来开启/dev/mem,确切的来说,官方开发组设置了一个内核命令行参数,即mem.devmem,若要启动/dev/mem,只要将mem.devmem置为真即可,即mem.devmem=1/Y/y。那么问题来了,要怎么设置这个参数呢,因为这个参数是在内核启动时传递过来的,众所周知,OpenBMC是由uboot来引导内核的,那么设置这个参数的重任自然就落在了uboot的身上,那么具体要怎么修改呢。其实很简单,修改如下:
修改步骤
- 修改uboot中
include/configs/ast-common.h
#define CONFIG_BOOTARGS "console=ttyS4,115200n8 root=/dev/ram rw"
修改为
#define CONFIG_BOOTARGS "console=ttyS4,115200n8 mem.devmem=y root=/dev/ram rw"
重新编译运行,即可看到/dev/mem已生成。
但是经过测试发现,OpenBMC只有在编译后第一次启动时这个“开关”才会出现,之后的多次测试启动均恢复到原来的启动参数,即使在物理机上测试也是同样的结果,到目前也没有弄明白是怎么回事。介于以上问题,只能使用终极方案了,即修改内核。
- 修改linux内核中
drivers/char/mem.c
static int __init chr_dev_init(void)
{
int minor;
if (register_chrdev(MEM_MAJOR, "mem", &memory_fops))
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
mem_class = class_create(THIS_MODULE, "mem");
if (IS_ERR(mem_class))
return PTR_ERR(mem_class);
mem_class->devnode = mem_devnode;
for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) {
if (!devlist[minor].name)
continue;
#ifdef CONFIG_DEVMEM_BOOTPARAM
if (minor == DEVMEM_MINOR && !devmem)
continue;
#endif
/*
* Create /dev/port?
*/
if ((minor == DEVPORT_MINOR) && !arch_has_dev_port())
continue;
device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor),
NULL, devlist[minor].name);
}
return tty_init();
}
修改为
static int __init chr_dev_init(void)
{
int minor;
devmem = true; //将开关置为真
if (register_chrdev(MEM_MAJOR, "mem", &memory_fops))
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
mem_class = class_create(THIS_MODULE, "mem");
if (IS_ERR(mem_class))
return PTR_ERR(mem_class);
mem_class->devnode = mem_devnode;
for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) {
if (!devlist[minor].name)
continue;
#ifdef CONFIG_DEVMEM_BOOTPARAM
if (minor == DEVMEM_MINOR && !devmem)
continue;
#endif
/*
* Create /dev/port?
*/
if ((minor == DEVPORT_MINOR) && !arch_has_dev_port())
continue;
device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor),
NULL, devlist[minor].name);
}
return tty_init();
}
修改后重新编译运行,/dev/mem将一直存在。