首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Yocto修补程序从外树模块导出具有外部符号的Linux内核树内模块

Yocto修补程序从外树模块导出具有外部符号的Linux内核树内模块
EN

Stack Overflow用户
提问于 2020-08-05 00:01:18
回答 1查看 724关注 0票数 0

我正在使用Yocto为我的嵌入式Linux项目构建一个SD卡映像。Yocto分支是Warrior,Linux内核版本为4.19.78-linux4sam-6.2。

我目前正在研究一种方法,从initramfs中的外部QSPI设备读取内存,并将内容放入procfs中的文件中。该部分工作正常,我将echo数据放入proc文件中,并在引导板后在用户空间Linux中成功地读取它。

现在,我需要使用Linux模块的EXPORT_SYMBOL()功能来允许一个在树中的内核模块了解我的出树自定义内核模块导出的符号。

在我的自定义模块中,我这样做:

代码语言:javascript
运行
复制
static unsigned char lan9730_mac_address_buffer[6];
EXPORT_SYMBOL(lan9730_mac_address_buffer);

我用以下方式修补了bbappend文件中的官方内核构建:

代码语言:javascript
运行
复制
diff -Naur kernel-source/drivers/net/usb/smsc95xx.c kernel-source.new/drivers/net/usb/smsc95xx.c
--- kernel-source/drivers/net/usb/smsc95xx.c    2020-08-04 22:34:02.767157368 +0000
+++ kernel-source.new/drivers/net/usb/smsc95xx.c        2020-08-04 23:34:27.528435689 +0000
@@ -917,6 +917,27 @@
 {
        const u8 *mac_addr;
 
+       printk("=== smsc95xx_init_mac_address ===\n");
+       printk("%x:%x:%x:%x:%x:%x\n",
+           lan9730_mac_address_buffer[0],
+           lan9730_mac_address_buffer[1],
+           lan9730_mac_address_buffer[2],
+           lan9730_mac_address_buffer[3],
+           lan9730_mac_address_buffer[4],
+           lan9730_mac_address_buffer[5]);
+       printk("=== mac_addr is set ===\n");
+       if (lan9730_mac_address_buffer[0] != 0xff &&
+           lan9730_mac_address_buffer[1] != 0xff &&
+           lan9730_mac_address_buffer[2] != 0xff &&
+           lan9730_mac_address_buffer[3] != 0xff &&
+           lan9730_mac_address_buffer[4] != 0xff &&
+           lan9730_mac_address_buffer[5] != 0xff) {
+           printk("=== SUCCESS ===\n");
+           memcpy(dev->net->dev_addr, lan9730_mac_address_buffer, ETH_ALEN);
+           return;
+       }
+       printk("=== FAILURE ===\n");
+
        /* maybe the boot loader passed the MAC address in devicetree */
        mac_addr = of_get_mac_address(dev->udev->dev.of_node);
        if (!IS_ERR(mac_addr)) {
diff -Naur kernel-source/drivers/net/usb/smsc95xx.h kernel-source.new/drivers/net/usb/smsc95xx.h
--- kernel-source/drivers/net/usb/smsc95xx.h    2020-08-04 22:32:30.824951447 +0000
+++ kernel-source.new/drivers/net/usb/smsc95xx.h        2020-08-04 23:33:50.486778978 +0000
@@ -361,4 +361,6 @@
 #define INT_ENP_TDFO_                  ((u32)BIT(12))  /* TX FIFO Overrun */
 #define INT_ENP_RXDF_                  ((u32)BIT(11))  /* RX Dropped Frame */
 
+extern unsigned char lan9730_mac_address_buffer[6];
+
 #endif /* _SMSC95XX_H */

但是,问题是内核无法使用此错误构建:

代码语言:javascript
运行
复制
|   GEN     ./Makefile
|   Using /home/me/Desktop/poky/build-microchip/tmp/work-shared/sama5d27-som1-ek-sd/kernel-source as source for kernel
|   CALL    /home/me/Desktop/poky/build-microchip/tmp/work-shared/sama5d27-som1-ek-sd/kernel-source/scripts/checksyscalls.sh
|   Building modules, stage 2.
|   MODPOST 279 modules
| ERROR: "lan9730_mac_address_buffer" [drivers/net/usb/smsc95xx.ko] undefined!

如何在修补的树内核模块中引用树外内核模块导出的符号?

initramfs相关代码:

代码语言:javascript
运行
复制
msg "Inserting lan9730-mac-address.ko..."
insmod /mnt/lib/modules/4.19.78-linux4sam-6.2/extra/lan9730-mac-address.ko
ls -rlt /proc/lan9730-mac-address
head -c 6 /dev/mtdblock0 > /proc/lan9730-mac-address

树外模块:

代码语言:javascript
运行
复制
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/slab.h>

const int BUFFER_SIZE = 6;

int write_length, read_length;
unsigned char lan9730_mac_address_buffer[6];
EXPORT_SYMBOL(lan9730_mac_address_buffer);

int read_proc(struct file *filp, char *buf, size_t count, loff_t *offp)
{
    // Read bytes (returning the byte count) until all bytes are read.
    // Then return count=0 to signal the end of the operation.

    if (count > read_length)
        count = read_length;

    read_length = read_length - count;
    copy_to_user(buf, lan9730_mac_address_buffer, count);

    if (count == 0)
        read_length = write_length;

    return count;
}

int write_proc(struct file *filp, const char *buf, size_t count, loff_t *offp)
{
    if (count > BUFFER_SIZE)
        count = BUFFER_SIZE;

    copy_from_user(lan9730_mac_address_buffer, buf, count);
    write_length = count;
    read_length = count;
    return count;
}

struct file_operations proc_fops = {
    read: read_proc,
    write: write_proc
};

void create_new_proc_entry(void)  //use of void for no arguments is compulsory now
{
    proc_create("lan9730-mac-address", 0, NULL, &proc_fops);
}

int proc_init (void) {
    create_new_proc_entry();
    memset(lan9730_mac_address_buffer, 0x00, sizeof(lan9730_mac_address_buffer));
    return 0;
}

void proc_cleanup(void) {
    remove_proc_entry("lan9730-mac-address", NULL);
}

MODULE_LICENSE("GPL");
module_init(proc_init);
module_exit(proc_cleanup);
EN

Stack Overflow用户

回答已采纳

发布于 2020-08-05 15:01:34

有几种方法可以实现您想要的东西(考虑到不同的方面,例如模块可以编译在模块中,也可以是模块)。

  1. 将树外模块转换为树内模块(在自定义内核构建中)。这将需要简单的导出和导入,就像您所做的那样,没有什么特殊的要求,只是可能提供一个带有符号的标头,并在模块安装后运行depmod -a。注意,您必须使用其他方式读取和满足dependencies.
  2. Turn的modprobe in-tree,即从树内模块导出符号,并将其保存在树外。在这种情况下,您只需检查它是否已归档(因为它是一个MAC地址,针对所有0的检查将有效,不需要额外的标志)

但是,这些方法都是错误的。驱动程序,甚至您的补丁清楚地显示它支持(设备树)和您的董事会有它的支持。所以,这是第一部分的解决方案,您可以使用设备树为网卡提供正确的MAC。

在您想要更改它的运行时,procfs方法一开始是非常奇怪的。Linux中的网络设备接口可以随时从用户空间更新MAC。只需使用ip命令,如/sbin/ip link set <$ETH> addr <$MACADDR>,其中<$ETH>是一个网络接口,例如,eth0和<$MACADDR>是需要设置的地址。

因此,如果这个问题是关于模块符号的,那么您需要为它找到更好的示例,因为它实际上取决于用例。您可以考虑阅读How to export symbol from Linux kernel module in this case?作为导出的另一种方式。另一种可能是如何正确地使用软件节点(这是最近Linux内核中的一个新概念)。

票数 1
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63256621

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档