Yocto Patch Linux Модуль ядра в дереве с внешним символом, экспортированным из модуля вне дерева - PullRequest
0 голосов
/ 05 августа 2020

Я использую Yocto для создания образа SD-карты для моего проекта Embedded Linux. Ветвь Yocto - Warrior , а версия ядра Linux - 4.19.78-linux4sam-6.2 .

В настоящее время я работаю над способом чтения памяти из внешнее устройство QSPI в initramfs и вставьте его содержимое в файл в procfs. Эта часть работает, и я echo данные в файл pro c и успешно считываю их позже в пространстве пользователя Linux после загрузки платы.

Теперь мне нужно использовать Linux Kernel module EXPORT_SYMBOL() функциональность, позволяющая модулю ядра в дереве знать о моем вневременном символе экспорта настраиваемого модуля ядра.

В моем настраиваемом модуле , Я делаю это:

static unsigned char lan9730_mac_address_buffer[6];
EXPORT_SYMBOL(lan9730_mac_address_buffer);

И я исправил официальную сборку ядра в файле bbappend bitbake следующим образом:

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 */

Однако проблема в том, что ядро ​​не может построить с эта ошибка:

|   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!

Как я могу сослаться на экспортированный символ модуля ядра Out-Of-Tree в исправленном модуле ядра In-Tree?

initramfs релевантно code:

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

Модуль Out-Of-Tree:

#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);

1 Ответ

1 голос
/ 05 августа 2020

Есть несколько способов добиться того, чего вы хотите (с учетом различных аспектов, например, модуль может быть скомпилирован или быть модулем).

  1. Преобразовать модуль Out-Of-Tree в In -Дерево одно (в вашей кастомной сборке ядра). Это потребует простого экспорта и импорта, как вы в основном это делали, и ничего особенного не требуется, просто, возможно, укажите заголовок с символом и depmod -a запустить после установки модуля. Обратите внимание, что вы должны использовать modprobe in-tree, который считывает и удовлетворяет зависимости.
  2. Поверните наоборот, т.е. экспортируйте символ из модуля в дереве и сохраните его вне дерева. В этом случае вам просто нужно проверить, был ли он зарегистрирован или нет (поскольку это адрес MA C, проверка на все 0 будет работать, дополнительные флаги не требуются)

НО , эти способы просто неправильные. Драйвер и даже ваш патч ясно показывают, что он поддерживает OF (дерево устройств), и ваша плата поддерживает его. Итак, это первая часть решения, вы можете предоставить правильный MA C сетевой карте с помощью дерева устройств.

В случае, если вы хотите изменить его во время выполнения, подход procfs очень странно начинать с участием. Интерфейс сетевого устройства в Linux имеет все средства для обновления MA C из пользовательского пространства в любое время, когда пользователь захочет это сделать. Просто используйте команду ip, например /sbin/ip link set <$ETH> addr <$MACADDR>, где <$ETH> - сетевой интерфейс, например eth0 , а <$MACADDR> - желаемый адрес для установки.

Итак, если этот вопрос скорее о символах модулей, вам нужно найти лучший пример для него, потому что это действительно зависит от варианта использования. Вы можете прочитать Как экспортировать символ из модуля ядра Linux в этом случае? в качестве альтернативы экспорту. Другой способ сделать это правильно - использовать программные узлы (это новая концепция в недавнем ядре Linux).

...