This shows you the differences between two versions of the page.
|
ass:labs-2025:03:tasks:02 [2025/08/06 11:56] florin.stancu created |
ass:labs-2025:03:tasks:02 [2026/07/16 11:35] (current) florin.stancu |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ==== 02. Enabling networking on iMX93 ==== | ==== 02. Enabling networking on iMX93 ==== | ||
| - | Notice that the FRDM-iMX93 has two Ethernet ports. | + | Notice that the FRDM-iMX93 has two Ethernet ports. But if you boot your previous Buildroot distro and try to see the available network: ''ip link show''. |
| - | But if you boot your previous Buildroot distro and try to see the available network: ''ip link show'', notice that they are missing. | + | In this task, you will have to debug the problem and try to fix it or at least find a workaround that lets you use your network interface. |
| - | TODO | + | Here are a few suggestions to get you started: |
| + | * Investigate your kernel's Device Tree Blob (dtb) and search for the ''ethernet'' node | ||
| + | * You can use the Device Tree Compiler tool **dtc** to convert between dtb and dts formats | ||
| + | * **dtc** is compiled automatically with Linux and can be found at ''linux/scripts/dtc/dtc'' | ||
| + | * Alternatively, it is packaged as ''dtc'' on Arch or ''device-tree-compiler'' on Ubuntu | ||
| + | * Use **dmesg** to view the kernel's boot log and search for any relevant messages | ||
| + | * ''grep -rn'' parts of any interesting message in the kernel's source to determine the context | ||
| + | * If you've compiled the kernel already, you can run ''./scripts/clang-tools/gen_compile_commands.py'' and it will generate a **compile_commands.json** file. This file can be used by your language server to allow you to *go to definition* or highlight code sections included in ''#ifdef''s. | ||
| + | * Try to identify the driver responsible for our network controller | ||
| + | * Remember that on ARM, drivers are matched to devices based on their ''compatible'' string from the DTB | ||
| + | * The driver must also have at least one of these strings written in its source files. | ||
| + | |||
| + | <spoiler Hint #1> | ||
| + | This line from **dmesg** tells us why the Network Interface Controller (NIC) remains unavailable. | ||
| + | |||
| + | <code> | ||
| + | [ 12.004678] platform 42890000.ethernet: deferred probe pending: platform: wait for supplier /soc@0/efuse@47510000/mac-address@4ec | ||
| + | </code> | ||
| + | </spoiler> | ||
| + | |||
| + | <spoiler Hint #2> | ||
| + | The driver can be found at ''linux/drivers/net/ethernet/freescale/fec_main.c''. \\ | ||
| + | There, the ''fec_get_mac()'' function will tell you how the driver gets the NIC's MAC address. \\ | ||
| + | Try to provide it via another means, other than through the eFuse protected by the EdgeLink Enclave (that doesn't work). | ||
| + | </spoiler> | ||
| + | |||
| + | <spoiler Hint #3> | ||
| + | In ''linux/net/ethernet/eth.c'' look at the comments of the ''fwnode_get_mac_address()'' function. \\ | ||
| + | This will give you some alternatives for the ''nvmem-cells'' and ''nvmem-cell-names'' properties that block the driver initialization. \\ | ||
| + | Try spoofing the MAC address of [[https://gist.github.com/aallan/b4bb86db86079509e6159810ae9bd3e4|some vendor]]. | ||
| + | </spoiler> | ||
| + | |||
| + | Once you are done, enable the **iperf3**, **iproute2** and **ethtool** network packages in Buildroot and build them. The compilation should not take more than 1-2 minutes. Re-generate ''linux.itb'' and copy it to the board's eMMC. | ||
| + | |||
| + | Connect to a colleague's board with an Ethernet cable. \\ | ||
| + | Use the ''ip'' command to **add** a static IP to your network interface (''man ip-address''). \\ | ||
| + | Then, use the ''iperf3'' tool to test the throughput and compare it to what **ethtool** advertises. \\ | ||
| + | Why is it not a full 1Gbps? | ||
| + | |||
| + | === Bonus: solving the actual cause of the problem === | ||
| + | |||
| + | The steps above might seem a bit hackish... that's because they are a ugly HACK working around the real problem! | ||
| + | |||
| + | And the real problem is: since the kernel was compiled with external modules (and they take ''~300MB''), | ||
| + | they were not included inside the initial ramdisk (obviously, since it's less than ''80MB'')! | ||
| + | |||
| + | Due to missing modules, the ethernet driver and its dependencies could not be properly initialized (actually, as we've debugged above, it's just missing its MAC address provider) and thus fails! | ||
| + | |||
| + | The real solution would be to install the buildroot-obtained rootfs (or any other method, tbh.), together with the external kernel modules (usually sitting inside ''/var/modules/7.x'' -- your kernel version). | ||
| + | |||
| + | This can be easily done by using the kernel's built-in install target: | ||
| + | |||
| + | <code bash> | ||
| + | # enter linux kernel source directory | ||
| + | cd linux/ | ||
| + | # create a target directory where external modules will be installed | ||
| + | mkdir -p "../linux-modules" | ||
| + | # install the modules | ||
| + | make ARCH=arm64 INSTALL_MOD_PATH="../linux-overlay" modules modules_install | ||
| + | # explore it! | ||
| + | ls -l ../linux-modules/lib/modules/* | ||
| + | </code> | ||
| + | |||
| + | Next, you will want to add the ''linux-modules'' directory into your Buildroot filesystem. | ||
| + | Fortunately, this is the easiest thing: enter buildroot's ''menuconfig'', search for ''ROOTFS_OVERLAY'' configuration item and set it to the **absolute path** of your ''linux-modules'' created above. | ||
| + | Do a ''make'' and voila! The rootfs archive will have a huge size (''>~350MB''), meaning we successfully added all available kernel modules. | ||
| + | |||
| + | There is one problem remaining, though: the rootfs won't fit anymore inside the uImage / small FAT32 partition... | ||
| + | So change of plans: delete the ''initrd'' node from ''linux.its'' (together with its ''ramdisk'' configuration node property) and rebuild the uImage. | ||
| + | |||
| + | Next, on the second partition inside your disk image, you must unpack the ''rootfs.tar'' file outputted by buildroot. Simply use ''tar xf ./path/to/rootfs.tar -C /mnt/your-ext4-partition/'' (check out the provided ''mk-disk-image.sh'' script!). | ||
| + | |||
| + | Still not finished: we need to add the following parameter to the kernel command line BEFORE booting Linux: ''root=/dev/mmcblk0p2''. This can be done inside u-boot, e.g., by using the ''setenv'' command: | ||
| + | <code> | ||
| + | # it's recommended to supply the whole cmdline value: | ||
| + | setenv bootargs "console=ttyLP0,115200 earlycon,115200 root=/dev/mmcblk0p2 rootwait clk_ignore_unused" | ||
| + | </code> | ||
| + | |||
| + | Otherwise, the kernel will complain that it cannot find the root block device and panic. | ||
| + | Check out the kernel boot log if you have any problems (it will also print its command line parameters it receives from the bootloader)! | ||
| + | |||
| + | If you successfully do all of this, you should see both ''eth'' interfaces: first one is 100Mbps, the second one is 1Gbps! | ||