Uboot 下识别带 CD-ROM 的 U盘报 *irq: data 错误
1 |
|
问题描述
带 CD-ROM 的U盘、硬盘在 uboot 下执行 usb star t报 *irq: data 刷屏打印。
问题原因
1、通过与 uboot 2010、u-boot 2016 对比发现并没有该问题。
2、加打印追踪函数,发现问题点在 disk/part_dos.c 下的 static int part_test_dos(struct blk_desc *dev_desc) 函数。
3、考虑到以往版本没问题,于是查看该文件的修改记录,发现了这笔提交。
1 |
|
这笔修改是觉得为 mbr 申请一个 legacy_mbr * dev_desc->blksz的内存空间太浪费了,申请一个 legacy_mbr 大小就够了。
4、checkout 这个修改,发现问题解决。
5、该笔提交与内存相关,继续追踪使用 mbr 的函数。
blk_dread(dev_desc, 0, 1, (ulong *)mbr) –> blkcache_read(block_dev->if_type, block_dev->devnum, start, blkcnt, block_dev->blksz, buffer) –> memcpy(buffer, src, blksz * blkcnt);
最后确定问题是因为 blkcache_read 内的 memcpy 越界了。
6、结合问题是发生在usb start 识别U盘阶段,在函数 part_test_dos 内部。我们认为识别存储类设备时,需要读取并解析其分区表,而分区表大小与设备的 sector 相关。sector即是block size,普通U盘 sector 大小是 512 byte,移动硬盘可能存在 4096 byte,对于 CD-ROM设备则是 2048 byte。
7、对结构体 legacy_mbr 大小的计算为 512 byte。
1 |
|
8、综上,src 对应的是 CD-ROM 的分区表,buffer 是 mbr,blksz为 2048,memcpy 自然会拷贝越界了。
1 |
|
解决方法
1、使用设备的 sector 大小确定函数 part_test_dos() 中 mbr 的大小,防止内存拷贝越界。
2、为了不浪费内存资源,我们决定这样修改。
1 |
|
3、后续通过 sector 大小为 512 byte 到 8192 byte 的虚拟U盘及 4096 byte 的移动硬盘验证,均正常识别,无 *irq: data 的刷屏打印了。