Rockchip u-boot stage command line and code to read the contents of the USB disk and parse it

U-boot is a commonly used boot loader for embedded systems. It can support a variety of devices and file systems, such as USB, SATA, FAT, EXT, etc. In the U-boot stage, we sometimes need to read some files from the USB disk/SD card and parse and process the file contents, such as obtaining some configuration parameters or loading some images. This blog will introduce two methods for reading and parsing the contents of a USB flash drive during the Rockchip u-boot stage: command line method and code method.

Command line mode

The command line method refers to entering some commands into the U-boot console to operate the U disk and file system. This method is relatively simple and intuitive, but has limited functions and can only perform some basic operations. The following are the specific steps for the command line method:

  1. Start U-boot and insert the USB flash drive into the motherboard.
  2. (Required) Enter the usb start command to start the USB subsystem and detect the device information of the USB flash drive. For example:
=> usb dev 0
USB is stopped. Please issue 'usb start' first.
//必须先执行usb start 不然执行其他usb xxx命令是不能用的
=> usb start
starting USB...
Bus dwc3@fcc00000: Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.10
Bus dwc3@fd000000: Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.10
Bus usb@fd800000: USB EHCI 1.00
Bus usb@fd840000: USB OHCI 1.0
Bus usb@fd880000: USB EHCI 1.00
Bus usb@fd8c0000: USB OHCI 1.0
scanning bus dwc3@fcc00000 for devices... 1 USB Device(s) found
scanning bus dwc3@fd000000 for devices... 2 USB Device(s) found
scanning bus usb@fd800000 for devices... 1 USB Device(s) found
scanning bus usb@fd840000 for devices... 1 USB Device(s) found
scanning bus usb@fd880000 for devices... 1 USB Device(s) found
scanning bus usb@fd8c0000 for devices... 1 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found
  1. Enter the usb info command to view the detailed information of the USB flash drive, including device number, manufacturer, product, type and capacity, etc. For example:
=> usb info
1: Hub,  USB Revision 3.0
 - U-Boot XHCI Host Controller 
 - Class: Hub
 - PacketSize: 512  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 1.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

1: Hub,  USB Revision 3.0
 - U-Boot XHCI Host Controller 
 - Class: Hub
 - PacketSize: 512  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 1.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

2: Mass Storage,  USB Revision 2.0
 - SanDisk Cruzer Glide 20042605620A22C31651
 - Class: (from Interface) Mass Storage
 - PacketSize: 64  Configurations: 1
 - Vendor: 0x0781  Product 0x5575 Version 1.38
   Configuration: 1
   - Interfaces: 1 Bus Powered 200mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 2
     - Class Mass Storage, Transp. SCSI, Bulk only
     - Endpoint 1 In Bulk MaxPacket 512
     - Endpoint 2 Out Bulk MaxPacket 512

1: Hub,  USB Revision 2.0
 - u-boot EHCI Host Controller 
 - Class: Hub
 - PacketSize: 64  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 1.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

1: Hub,  USB Revision 1.10
 -  U-Boot Root Hub 
 - Class: Hub
 - PacketSize: 8  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 0.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 2 Interval 255ms

1: Hub,  USB Revision 2.0
 - u-boot EHCI Host Controller 
 - Class: Hub
 - PacketSize: 64  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 1.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

1: Hub,  USB Revision 1.10
 -  U-Boot Root Hub 
 - Class: Hub
 - PacketSize: 8  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 0.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 2 Interval 255ms

=> usb storage
  Device 0: Vendor: SanDisk  Rev: 1.26 Prod: Cruzer Glide    
            Type: Removable Hard Disk
            Capacity: 7633.5 MB = 7.4 GB (15633408 x 512)
=>
  1. Enter the part usb command to view the partition table of the USB flash drive, including partition number, starting sector, number of sectors, UUID and type, etc. For example:
=> usb part

Partition Map for USB device 0  --   Partition Type: DOS

Part	Start Sector	Num Sectors	UUID		Type
  4	256       	15633152  	cad4ebea-04	0c Boot
  1. Enter the fs_set_blk_dev <dev[:part]> command to set the U disk as the current device and file system, where interface is usb, dev is the device number, part is the partition number, and fstype is the file system type, which can be FS_TYPE_ANY, FS_TYPE_FAT, FS_TYPE_EXT wait. For example:
=> fs_set_blk_dev usb 0:4 FS_TYPE_ANY
  1. Enter the fs_size command to get the size of a file in the USB flash drive and assign it to a variable. For example:
=> fs_size uboot_file file_size
24 bytes read in 22 ms (1000 Bytes/s)
  1. Enter fatload usb 0:4 <addr> <filename>the command to read the contents of a file from the USB flash drive and store it at the specified memory address. where filenameis the file name and addris the memory address. For example:
=> fatload usb 0:4 0x007ef000 uboot_file
reading uboot_file
24 bytes read in 22 ms (1000 Bytes/s)
  1. Enter md.b <addr> <len>the command to view the file contents in memory, where addris the memory address and lenis the number of bytes to be viewed. For example:
=> md.b 0x007ef000 512
007ef000: 6c 63 64 5f 78 3d 31 39 32 30 3b 0d 0a 6c 63 64    lcd_x=1920;..lcd
007ef010: 5f 79 3d 31 30 38 30 3b ff ff ff ff ff ff ff ff    _y=1080;........
007ef020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
007ef030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
007ef040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
007ef050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
  1. Carry out corresponding analysis and processing according to the format and meaning of the file content. For example, if the file content is some key-value pairs, we can use the strtok function to split the string and the strtol function to convert the numerical value. For example:
char *ptr_x = strtok(buffer, "=");
char *ptr_y = strtok(NULL, "=");
long lcd_x = strtol(ptr_x, NULL, 10);
long lcd_y = strtol(ptr_y, NULL, 10);
printf("lcd_x = %ld, lcd_y = %ld\n", lcd_x, lcd_y);

code method

The code method refers to writing some functions or commands in the source code of U-boot to operate the U disk and file system. This method is more flexible and powerful, but it requires certain programming knowledge and compilation environment. The following are the specific steps of the code:

  1. Enter the source code of Rockchip u-boot to configure and compile u-boot.
  2. Create a new C file in the drivers/usb/gadget directory, such as usb_file_parser.c, and include some necessary header files, such as common.h, command.h, fs.h, usb.h, etc.
  3. Define a new function in the usb_file_parser.c file, such as do_read_uboot_file, and implement the logic of reading and parsing files from the USB disk. You can refer to the sample code in the link below to implement this function.
  4. Define a new command structure in the usb_file_parser.c file, such as read_uboot_file_cmd, and specify the command name, number of parameters, repeatability, function pointer, description and usage, etc.
  5. Use the U_BOOT_CMD macro in the usb_file_parser.c file to register this new command and add it to the u-boot command list.
  6. Add usb_file_parser.o to the obj-y variable in the drivers/usb/gadget/Makefile file for compilation. Recompile
    u-boot and burn it to the motherboard.

```bash
#include <common.h>
#include <command.h>
#include <fs.h>
#include <usb.h>
#include <stdlib.h>

#define FILE_PATH "uboot_file"
#define BUFFER_SIZE 512

int do_read_uboot_file(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
    
    
    char buffer[BUFFER_SIZE + 1];
    loff_t file_size, actread;
    int ret;
    // 启动USB子系统
    //usb_stop();
   // usb_start(); //没有这个 
    // 设置U盘为当前设备和文件系统,根据实际情况修改设备号和分区号
    if (fs_set_blk_dev("usb", "0:4", FS_TYPE_ANY)) {
    
    
        printf("Error setting block device.\n");
        return 1;
    }

    // 获取文件大小
    if (fs_size(FILE_PATH, &file_size) < 0) {
    
    
        printf("Error getting size of %s\n", FILE_PATH);
        return 1;
    }

    // 确保不尝试读取超出文件大小的内容
    if (file_size > BUFFER_SIZE) {
    
    
        printf("File is larger than buffer. Adjust BUFFER_SIZE.\n");
        return 1;
    }


    // 读取文件,选择一个合适的内存地址,避免与其他内存区域冲突
    actread = 0;
    //ret = fs_read(FILE_PATH, (ulong)0x60000000, 0, 0, &actread); // 修改这一行
   // ret = fs_read(FILE_PATH, (ulong)buffer, 0, file_size, &actread);
   //ret = fs_read(FILE_PATH, (ulong)0x60000000, 0, file_size, &actread);
    ret = fs_read(FILE_PATH, (ulong)0x7ef000, 0, file_size, &actread);
    if (ret) {
    
    
        printf("fs_read returned error code: %d\n", ret);
    }
    if (actread != file_size) {
    
    
        printf("Expected to read %lld bytes but read %lld bytes\n", file_size, actread);
    }
    if (ret || actread != file_size) {
    
    
        printf("Error reading %s\n", FILE_PATH);
        return 1;
    }

    // 确保字符串以null结尾
    buffer[actread] = '\0';

    // 解析文件内容
    char *ptr_x = strstr(buffer, "lcd_x=");
    char *ptr_y = strstr(buffer, "lcd_y=");
    if (ptr_x && ptr_y) {
    
    
        int lcd_x = simple_strtoul(ptr_x + 6, NULL, 10);
        int lcd_y = simple_strtoul(ptr_y + 6, NULL, 10);
        printf("lcd_x = %d, lcd_y = %d\n", lcd_x, lcd_y);
    } else {
    
    
        printf("Failed to parse the file\n");
    }
    return 0;
}

U_BOOT_CMD(
    read_uboot_file,    // command name
    1,                  // maxargs
    1,                  // repeatable
    do_read_uboot_file, // command function
    "Read and parse the uboot_file from USB",  // description
    "This command reads the uboot_file from USB and parses lcd_x and lcd_y values"  // usage
);

  1. Add more printf statements in the fs_read function of fs.c to obtain more detailed debugging information.
int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
            loff_t *actread)
{
    
    
        struct fstype_info *info = fs_get_info(fs_type);
        void *buf;
        int ret;

        // 增加的打印
        printf("fs_read called with:\n");
        printf("filename: %s\n", filename);
        printf("addr: %lx\n", addr);
        printf("offset: %lld\n", offset);
        printf("len: %lld\n", len);

        buf = map_sysmem(addr, len);
        if (!buf) {
    
    
            printf("Error mapping memory at address %lx\n", addr);
            return -1;
        }

        ret = info->read(filename, buf, offset, len, actread);

        // 增加的打印
        if (ret) {
    
    
            printf("info->read returned error code: %d\n", ret);
        }
        if (actread && *actread != len) {
    
    
            printf("Expected to read %lld bytes but read %lld bytes\n", len, *actread);
        }

        unmap_sysmem(buf);

        /* If we requested a specific number of bytes, check we got it */
        if (ret == 0 && len && *actread != len)
                printf("** %s shorter than offset + len **\n", filename);
        fs_close();

        return ret;
}
  1. Start u-boot and insert the USB flash drive into the motherboard.
  2. Enter the read_uboot_file command to execute the function that reads and parses the file from the USB flash drive, and view the output results. For example:
//必须先执行usb start 不然执行其他usb xxx命令是不能用的
=> usb start
starting USB...
Bus dwc3@fcc00000: Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.10
Bus dwc3@fd000000: Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.10
Bus usb@fd800000: USB EHCI 1.00
Bus usb@fd840000: USB OHCI 1.0
Bus usb@fd880000: USB EHCI 1.00
Bus usb@fd8c0000: USB OHCI 1.0
scanning bus dwc3@fcc00000 for devices... 1 USB Device(s) found
scanning bus dwc3@fd000000 for devices... 2 USB Device(s) found
scanning bus usb@fd800000 for devices... 1 USB Device(s) found
scanning bus usb@fd840000 for devices... 1 USB Device(s) found
scanning bus usb@fd880000 for devices... 1 USB Device(s) found
scanning bus usb@fd8c0000 for devices... 1 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found
//----------------------
//uboot 反正目前一直是下面这个打印 能读到文件大小,但就是代码读不到文件内容。
//真™快吐了,折腾了我将近4小时 后面有时间在研究,
=> read_uboot_file 
fs_read called with:
filename: uboot_file
addr: 7ef000
offset: 0
len: 24
info->read returned error code: -1
Expected to read 24 bytes but read 0 bytes
fs_read returned error code: -1
1 Expected to read 24 bytes but read 0 bytes
Error reading uboot_file
=> 
//代码正确打印应该是
reading uboot_file
fs_read called with:
filename: uboot_file
addr: 7ef000
offset: 0
len: 0
reading uboot_file
Expected to read 0 bytes but read 24 bytes
lcd_x = 1920, lcd_y = 1080

//命令行正确打印
=> fatload usb 0:4 0x007ef000 uboot_file
fs_read called with:
filename: uboot_file
addr: 7ef000
offset: 0
len: 0
reading uboot_file
Expected to read 0 bytes but read 24 bytes
=> md.b 0x007ef000 512
007ef000: 6c 63 64 5f 78 3d 31 39 32 30 3b 0d 0a 6c 63 64    lcd_x=1920;..lcd
007ef010: 5f 79 3d 31 30 38 30 3b ff ff ff ff ff ff ff ff    _y=1080;........
007ef020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
007ef030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
007ef040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
007ef050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................

Update 20230828
I changed my mind. Since fs_readthe function cannot be read, I just run_commandread it directly (refer to uboot's way of reading the logo), and it succeeded.
But there is currently a disadvantage that you still need to manually execute usb start, and you run_command("usb start", 0)will be prompted if you pass Bad device usb 0 .
Insert image description here

=> usb start
starting USB...
Bus dwc3@fcc00000: Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.10
Bus dwc3@fd000000: Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.10
Bus usb@fd800000: USB EHCI 1.00
Bus usb@fd840000: USB OHCI 1.0
Bus usb@fd880000: USB EHCI 1.00
Bus usb@fd8c0000: USB OHCI 1.0
scanning bus dwc3@fcc00000 for devices... 1 USB Device(s) found
scanning bus dwc3@fd000000 for devices... 2 USB Device(s) found
scanning bus usb@fd800000 for devices... 1 USB Device(s) found
scanning bus usb@fd840000 for devices... 1 USB Device(s) found
scanning bus usb@fd880000 for devices... 1 USB Device(s) found
scanning bus usb@fd8c0000 for devices... 1 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found
=> read_uboot_file 
fs_read called with:
filename: uboot_file
addr: 7ef000
offset: 0
len: 0
reading uboot_file
Expected to read 0 bytes but read 24 bytes
24 bytes read in 32 ms (0 Bytes/s)
lcd_x = 1920, lcd_y = 1080

#include <common.h>
#include <command.h>
#include <fs.h>
#include <usb.h>
#include <stdlib.h>

#define FILE_PATH "uboot_file"
#define BUFFER_SIZE 512

int do_read_uboot_file(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
    
    
    //char buffer[BUFFER_SIZE + 1]; //这个一定是要选一个可用的地址 不能这么干 可能读不到
    char *buffer = (char *)0x007ef000;  // 直接使用该地址
    char cmd[BUFFER_SIZE] = {
    
    "0"}; // 添加命令缓冲区

    // 初始化USB
    /*if (run_command("usb start", 0)) {
    
    
        printf("Error initializing USB.\n");
        return 1;
    }*/

    // 使用fatload命令读取文件到指定地址
    sprintf(cmd, "fatload usb 0:4 0x007ef000 %s", FILE_PATH);
    if (run_command(cmd, 0)) {
    
    
        printf("Error reading %s using fatload\n", FILE_PATH);
        return 1;
    }

    // 解析文件内容
    char *ptr_x = strstr(buffer, "lcd_x=");
    char *ptr_y = strstr(buffer, "lcd_y=");
    if (ptr_x && ptr_y) {
    
    
        int lcd_x = simple_strtoul(ptr_x + 6, NULL, 10);
        int lcd_y = simple_strtoul(ptr_y + 6, NULL, 10);
        printf("lcd_x = %d, lcd_y = %d\n", lcd_x, lcd_y);
    } else {
    
    
        printf("Failed to parse the file\n");
    }
    return 0;
}

U_BOOT_CMD(
    read_uboot_file,    // command name
    1,                  // maxargs
    1,                  // repeatable
    do_read_uboot_file, // command function
    "Read and parse the uboot_file from USB",  // description
    "This command reads the uboot_file from USB and parses lcd_x and lcd_y values"  // usage
);

Summarize

This blog introduces two methods for reading and parsing the contents of a USB flash drive during the Rockchip u-boot stage: command line method and code method. The command line method is relatively simple and intuitive, but its functions are limited and can only implement some basic operations.

Guess you like

Origin blog.csdn.net/SHH_1064994894/article/details/132515787