U-boot Script Bad Header CRC - u-boot

I have a "flashing" script being loaded into a Uboot, on an iMX6, from a host PC via sdp. The script has been run through mkimage, so it has an image header. Here's the mkimage command:
mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "U-Boot script" -d $files_dir$flash_txt $files_dir$flash_scr
I can parse the header with binwalk:
$ binwalk -B flash.scr
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 uImage header, header size: 64 bytes, header CRC: 0x315E128A, created: 2021-09-13 14:52:46, image size: 2406 bytes, Data Address: 0x0, Entry Point: 0x0, data CRC: 0x7B909BAE, OS: Linux, CPU: ARM, image type: Script file, compression type: none, image name: "U-Boot script"
It fails to execute, with the uboot saying "Bad Header CRC". So, I'm trying to at least force it to work, while on the device, by correcting the CRC on the spot, using the built-in crc32 tool. It still won't work.
Here are uboot commands I'm trying (after the script is already in memory at address 0x10100000):
# display the script bytes
md 0x10100000
# reset the crc
mw 0x10100004 0x0 1
# verify the change
md 0x10100000
# recalc the crc
crc32 0x10100000 64
# write the crc
#mw 0x10100004 <VALUE> 1
# example:
mw 0x10100004 0x3a833d99 1
# run the script
source 0x10100000
When I do this, I still get the dreaded "Bad Header CRC" error!
I've found numerous sources which reveal / indicate which bytes contain the "header CRC". I've seen multiple sources saying that one needs to "reset" the checksum prior to attempting to compute it. This all looks to be valid logic. What am I doing wrong?
Update
The CORRECT uboot input / results
Per help from sawdust
...
Bad header crc
CTRL+C - Operation aborted.
SDP ended
uboot# md 0x10100000
10100000: 56190527 229a2e76 f4f64161 66090000 '..Vv.."aA.....f
10100010: 00000000 00000000 0533a380 00060205 ..........3.....
10100020: 6f422d55 7320746f 70697263 00000074 U-Boot script...
10100030: 00000000 00000000 00000000 00000000 ................
10100040: 5e090000 00000000 20766e65 61666564 ...^....env defa
10100050: 20746c75 2d20662d 65730a61 766e6574 ult -f -a.setenv
10100060: 7a697320 79625f65 685f6574 725f7865 size_byte_hex_r
10100070: 66746f6f 33352073 35453937 65730a41 ootfs 5379E5A.se
10100080: 766e6574 7a697320 6c625f65 5f6b636f tenv size_block_
10100090: 5f786568 746f6f72 32207366 30444239 hex_rootfs 29BD0
101000a0: 7465730a 20766e65 657a6973 7479625f .setenv size_byt
101000b0: 65685f65 62755f78 20746f6f 30433337 e_hex_uboot 73C0
101000c0: 65730a30 766e6574 7a697320 6c625f65 0.setenv size_bl
101000d0: 5f6b636f 5f786568 6f6f6275 39332074 ock_hex_uboot 39
101000e0: 730a0a45 6e657465 6f722076 7366746f E..setenv rootfs
101000f0: 6c5f615f 6c656261 6f722220 7366746f _a_label "rootfs
uboot# mw 0x10100004 0x0 1
uboot# crc32 0x10100000 0x40 0x10100004
crc32 for 10100000 ... 1010003f ==> 94926f83
uboot# md 0x10100000
10100000: 56190527 836f9294 f4f64161 66090000 '..V..o.aA.....f
10100010: 00000000 00000000 0533a380 00060205 ..........3.....
10100020: 6f422d55 7320746f 70697263 00000074 U-Boot script...
10100030: 00000000 00000000 00000000 00000000 ................
10100040: 5e090000 00000000 20766e65 61666564 ...^....env defa
10100050: 20746c75 2d20662d 65730a61 766e6574 ult -f -a.setenv
10100060: 7a697320 79625f65 685f6574 725f7865 size_byte_hex_r
10100070: 66746f6f 33352073 35453937 65730a41 ootfs 5379E5A.se
10100080: 766e6574 7a697320 6c625f65 5f6b636f tenv size_block_
10100090: 5f786568 746f6f72 32207366 30444239 hex_rootfs 29BD0
101000a0: 7465730a 20766e65 657a6973 7479625f .setenv size_byt
101000b0: 65685f65 62755f78 20746f6f 30433337 e_hex_uboot 73C0
101000c0: 65730a30 766e6574 7a697320 6c625f65 0.setenv size_bl
101000d0: 5f6b636f 5f786568 6f6f6275 39332074 ock_hex_uboot 39
101000e0: 730a0a45 6e657465 6f722076 7366746f E..setenv rootfs
101000f0: 6c5f615f 6c656261 6f722220 7366746f _a_label "rootfs
uboot# source 0x10100000
## Executing script at 10100000
... SUCCESS!!!!!
Pre-upload PC Patch
After running mkimage, I fixed the CRC in this way. This could be written in a more elegant fashion I'm sure - but this proved functional at least:
# The mkimage "header CRC" is invalid for some reason, so it needs to be corrected!
$files_dir=files/
$flash_scr=flash.scr
$flash_hdr=flash.hdr
chmod 644 $files_dir$flash_scr
# zero the current crc, and copy the 64 byte header to a separate file
printf '\x00\x00\x00\x00' | dd of=$files_dir$flash_scr bs=1 seek=4 count=4 conv=notrunc
head -c 64 $files_dir$flash_scr > $files_dir$flash_hdr
# calculate the correct crc
crc=$(crc32 $files_dir$flash_hdr)
b1=$(echo $crc | cut -c 1,2)
b2=$(echo $crc | cut -c 3,4)
b3=$(echo $crc | cut -c 5,6)
b4=$(echo $crc | cut -c 7,8)
# update the script, with the correct value
printf "\x${b1}\x${b2}\x${b3}\x${b4}" | dd of=$files_dir$flash_scr bs=1 seek=4 count=4 conv=notrunc
# clean up
rm $files_dir$flash_hdr
The fundamental flaw in mkimage
Ideally, mkimage would do its job correctly in the first place. Why it is malfunctioning is still a mystery...

What am I doing wrong?
U-Boot almost always assumes hexadecimal values for command arguments, so using the 0x... prefix is actually superfluous. AFAIK there is no way to input decimal values.
# recalc the crc
crc32 0x10100000 64
So when you specify the length of the header in the crc32 command as 64, you have specified an incorrect (header) length of 0x64 or 100 decimal.
Reviewing the U-Boot command response confirms your mistake:
=> crc32 0x10100000 64
CRC32 for 10100000 ... 10100063 ==> 9988c6ca
The address range of 0x10100000 through 0x10100063 is a span of 100 bytes.
Addendum (with revisions)
When you install the calculated value, you are probably introducing an endian (byte order) issue.
# write the crc
#mw 0x10100004 <VALUE> 1
The calculated CRC32 value probably needs to specified in reverse byte-order (assuming little-endian mode for the i.MX6) in the mw command.
For example, the mkimage command installs an original header CRC32 value of d8bc0e3a 3a0ebcd8 in the second word (in little-endian order):
=> md 20000000
20000000: 56190527 3a0ebcd8 a0284161 1f000000 '..V...:aA(.....
20000010: ...
=> imi 20000000
## Checking Image at 20000000 ...
Legacy image found
Image Name: U-Boot script
Image Type: PowerPC Linux Script (uncompressed)
Data Size: ...
After zeroing the second word, the CRC32 command produces the (same) value (as expected) (but as a 4-byte string rather than an integer):
=> crc32 20000000 40
crc32 for 20000000 ... 2000003f ==> d8bc0e3a
If you install this value literally using the mw command, then the byte order is not what is required for a 32-bit word value.
=> mw 20000004 d8bc0e3a
=> md 20000000
20000000: 56190527 d8bc0e3a a0284161 1f000000 '..V:...aA(.....
20000010: ...
=> imi 20000000
## Checking Image at 20000000 ...
Legacy image found
Bad Header Checksum
=>
The mw command treats the value to write as a byte string rather than an integer value an integer value, and therefore does not perform a byte reordering (even though this is a little-endian CPU) a byte reordering of the CRC32 value is required.
Addendum 2
Slight corrections to above in regards to which U-Boot commands are displaying results in little-endian mode.
The md command is displaying word values assuming the stored value is in little-endian mode.
To see the true byte order in memory, use the md.b command.
=> md 20000000 4
20000000: 56190527 3a0ebcd8 a0284161 1f000000 '..V...:aA(.....
=> md.b 20000000 10
20000000: 27 05 19 56 d8 bc 0e 3a 61 41 28 a0 00 00 00 1f '..V...:aA(.....
=>
Therefore, the mkimage command installs an original header CRC32 value of 3a0ebcd8 in the second word (in little-endian order).
The CRC32 command produces the 4-byte value as a byte string (i.e. already in little-endian order).
The mw command is aware that this is a little-endian CPU, and does treats the value to write as an integer value.
Since the CRC32 result is a byte string (rather than an integer value), these bytes must be reordered for input using the mw command.
Got that?
One possible way to avoid this endian confusion would be to use the automatic write feature of the CRC32 command.
Append the address of the header CRC to your crc32 command, and the calculated value will be stored in the correct order for you, e.g.
crc32 0x10100000 0x40 0x10100004
Still wonder why you don't have a good CRC32 in the first place using mkimage, and why you had to resort to this hack.

Related

How to accomplish this byte munging in perl?

Background:
I'm trying to use the perl script from here to decrypt an android backup. Unfortunately, the checksum validation fails.
After playing around with this (Python) script, the problem seems to be that I need to do some additional munging of the master key (n.b. masterKeyJavaConversion in the Python script).
Problem:
I need to take a bag of bytes and perform the following conversion steps:
Sign-extend from signed char to signed short
Convert the result from UTF16 (BE?) to UTF-8
For example (all bytes are in hex):
3x → 3x
7x → 7x
ax -> ef be ax
bx -> ef be bx
cx -> ef bf 8x
dx -> ef bf 9x
ex -> ef bf ax
fx -> ef bf bx
(The x always remains unchanged.)
More specifically, given a bit sequence 1abc defg, I need to output 1110 1111 1011 111a 10bc defg. (For 0abc defg, the output is just 0abc defg, i.e. unchanged.)
Answers may use UTF conversions or may do the bit twiddling directly; I don't care, as long as it works (this isn't performance-critical). Answers in the form of a subroutine are ideal. (My main problem is I know just enough Perl to be dangerous. If this was C/C++, I wouldn't need help, but it would be a major undertaking to rewrite the entire script in another language, or to modify the Python script to not need to read the entire input into memory.)
1110 1111 1011 111a 10bc defg would be a valid UTF-8 encoding.
++++-------------------------- Start of three byte sequence
|||| ++------------------- Continuation byte
|||| || ++---------- Continuation byte
|||| || ||
11101111 1011111a 10bcdefg
|||| |||||| ||||||
++++---++++++---++++++---- 1111 1111 1abc defg
That's just the extension of an 8-bit signed number to 16 bits, cast to unsigned, and treated as a Unicode Code Point.
So, without looking at the code, I think you want
sub encode_utf8 {
my ($s) = #_;
utf8::encode($s);
return $s;
}
sub munge {
return
encode_utf8 # "\x30\x70\xEF\xBE\xA0..."
pack 'W*', # "\x{0030}\x{0x0070}\x{0xFFA0}..."
unpack 'S*', # 0x0030, 0x0070, 0xFFA0, ...
pack 's*', # "\x30\x00\x70\x00\xA0\xFF..." (on a LE machine)
unpack 'c*', # 48, 112, -96, ...
$_[0]; # "\x30\x70\xA0..."
}
my $s = "\x30\x70\xA0\xB0\xC0\xD0\xE0\xF0";
my $munged = munge($s);
If you remove the comments, you get the following:
sub munge {
my $s = pack 'W*', unpack 'S*', pack 's*', unpack 'c*', $_[0];
utf8::encode($s);
return $s;
}
Here's a much faster solution:
my #map = (
( map chr($_), 0x00..0x7F ),
( map "\xEF\xBE".chr($_), 0x80..0xBF ),
( map "\xEF\xBF".chr($_), 0xC0..0xFF ),
);
sub munge { join '', #map[ unpack 'C*', $_[0] ] }
This may not be as elegant as ikegami's answer, but it worked:
sub munge_mk
{
my $out;
foreach(unpack('C*', $_[0])) {
if($_ < 128) {
$out .= chr($_);
} else {
my $hi = 0xbc | (($_ & 0xc0) >> 6);
my $lo = 0x80 | ($_ & 0x3f);
$out .= chr(0xef) . chr($hi) . chr($lo);
}
}
return $out;
}

ARM NEON to aarch64

I have code for ARM NEON armv7-a:
vst2.u8 {d1,d3}, [%1]!
I port it to aarch64 like that:
st2 {v1.8b,v3.8b},[%1],#16
and got an error: Error: invalid register list at operand 1 -- `st2 {v1.8b,v3.8b},[x1],#16'
In accordance with doc this is valid:
ST2 {Vt.<T>, Vt+2.<T>}, vaddr
I can't figure out the problem.
p.s. if i change it like
st2 {v1.8b,v2.8b},[%1],#16
the compiler doesn't break with error message
I am refering to the ARM a64 instruction set architecture here, which was last updated in 2018.
The first link in your comment was only about the aarch32 instruction set. The second link was about the aarch64 instruction set, but it's titled as iterim in the pdf title and was published 2011. The format
ST2 { <Vt>.<T>, <Vt+2>.<T> }, vaddr
is mentioned there (page 89), but this is not included in the current version.
Encoding of ST2
In the current version, ST2 is coded for multiple data structures as follows (see page 1085):
┌───┬───┬──────────┬───┬───────┬──────┬────┬───────┬───────┐
│ 0 │ Q │ 00110010 │ I │ mmmmm │ 1000 │ ss │ nnnnn │ ttttt │
└───┴───┴──────────┴───┴───────┴──────┴────┴───────┴───────┘
Rm size Rn Rt
There are three types of offset the instruction can be used with:
No offset (Rm == 000000 and I == 0):
ST2 { <Vt>.<T>, <Vt2>.<T> }, [<Xn|SP>]
Immediate offset (Rm == 111111 and I == 1):
ST2 { <Vt>.<T>, <Vt2>.<T> }, [<Xn|SP>], <imm>
Register offset (Rm != 111111 and I == 1):
ST2 { <Vt>.<T>, <Vt2>.<T> }, [<Xn|SP>], <Xm>
<imm> is #16 or #32 here, regarding to Q. Only the first register's index t is saved in the encoding here. The second register's index is always calculated as t+1 mod 32.
That's why you got the error: the registers must follow one another. There is simply not enough space to encode the second register separately. The two index registers already take up too much lot of space.
Consideration
Wouldn't it be possible to encode the second register? In the case I == 0, Rm is set to 00000, but that's just conventional. This register could be used for our purpose, but only in the case that no immediate or register offset is specified.
I also see the reason why the format with <Vt+2> was not adopted from the draft: it can only be coded for this special case. The implementation would make the implementation of the chip more complex and simply not worthwhile.

How to find source data of file in FAT32 by clusters and FAT table?

I have some FAT32 structure output:
bytes_per_sector 0x200
sectors_per_cluster 0x8
reserved_sector_count 0x780
FATtable_count 0x2
root_entry_count 0
hidden_sector_count 0x38
total_sectors_32 0xf17fc8
FATtable_size_32 0x3c40
root_cluster 0x2
fat_info 0x1
backup_BS_sector 0x6
Ok, assume to this information, I jump over reserved_sector_count and get the FAT32 table. #1920 - is offset from te begining - 0x780.
fat32Table #1920
cluster0 ffffff8
cluster1 ffffffff
cluster2 fffffff
cluster3 fffffff
Ok, assume to FATtable_size_32 and FATtable_count I jump over and get to the Data Region at the position #16777216 from the begining. This is the 0 cluster, as I understand. Cluster consists of 8 sectors by 512 byte each. First Directory named "F" - is volume. Second "HELLO.TXT" is a file. DirectoryEntry size of 32 byte.
name #16777216 46 [F ]
ext [ ]
attrib 8
NTreserved 0
CrtTimeTenth 0
createtime 0
createdate 0
accessdate 0
clusterhigh 0
modifiedtime 81e3
modifieddate 4ace
clusterlow 0
filesize 0
name #16777216 48 [HELLO ]
ext [TXT]
attrib 20
NTreserved 18
CrtTimeTenth 5c
createtime 82ca
createdate 4ace
accessdate 4ace
clusterhigh 0
modifiedtime 82d4
modifieddate 4ace
clusterlow 3
filesize 24
Next, I want to find data according to "hello.txt" file. I see clusterlow= 0x03. When I jump to next cluster (+4096 byte) and see data of my file.
name #16781312 This is test
But I don't get how does clusterlow help me to find it? What clusters ffffff8, ffffffff, fffffff in FAT32 table? How to find source data according to all this stuff?
#tilz0R, thanks for a link, but I have already read a doc from MS. And more.
I just get that at the DataRegion (after reserved sectors and FAT32 table) we begin with the cluster2, and clusterlow=0x03 means that source data located in the next cluster3 which is +4096 byte lower than cluster2.
It was easier to understand when I add one more file on a disk and see that first file located in the cluster3 and the second - cluster4.

FindFirstFile and FindNextFile crash my program in assembly. Why?

I am writing a program that looking for files with the extension ".fly". It displays the names of the founded files, but when I try to use FindFirstFile and FindNextFile, my program crashes. I have tried with FindFirstFileA (ANSI Version of the function) , but my code crashes too. Please, give me a example of code if it's possible.
Please, thanks for your answers. Here's my source code written in FASM Assembly
format pe console 4.0
include 'C:\fasm\INCLUDE\WIN32AX.INC'
; Declare a macro to make buffers
macro dup label,lcount
{ forward
label#:
common
repeat lcount
forward
db 0
common
end repeat }
.code
main:
explore_directoy:
invoke FindFirstFile,file_extension, FIND_STRUCT ; find the first *.fly
mov dword [find_handle], eax
find_more_files:
cmp eax, 0
je exit
call show_file
findnextfile:
invoke FindNextFile, dword [find_handle], FIND_STRUCT
jmp find_more_files
show_file:
invoke MessageBox, NULL, addr msg, addr msg_caption, MB_OK ; Easy way of outputing the text
;invoke MessageBox, NULL, addr cFileName, addr msg_caption, MB_OK
ret
exit:
invoke ExitProcess, 0
datazone:
end_msg db 'End of program', 0
msg db 'File founded', 0
msg_caption db 'Assembly program...', 0
file_extension db '*.fly', 0
find_handle dd 0 ; handles/other stuff..
FIND_STRUCT: ; find structure used with searching
dwFileAttributes dd 0
ftCreationTime dd 0,0
ftLastAccessTime dd 0,0
ftLastWriteTime dd 0,0
nFileSizeHigh dd 0
nFileSizeLow dd 0
dwReserved0 dd 0
dwReserved1 dd 0
dup cFileName, 256 ; found file buffer
dup cAlternate, 14
.end main
Your .text section isn't writable. Change
.code
to
section '.text' readable writable executable
Data should go into the .data section, not the .code section. If your assembler supports uninitialized data (all values defined as ?), then it should go into the .data? section (this is the equivalent of a bss (block started by symbol) section used in some other assemblers).

capturing webcam stream with V4L2 failed

I am getting started with the V4L2 framework on Ubuntu 10.4.
currently I am using an webcam to do some tests. I am following this documentation to start, the installation was worked fine. I downloaded and compiled the application example. The problems is video output,I call the executable using:
# modprobe -r pwc
# modprobe -v pwc fps=15 compression=3 mbufs=4 fbufs=4 size=vga
# ./capturer_mmap -D /dev/video0 -w 640*480 -p 0 | ./viewer -w 640*480 -p 0
given this output:
Output on terminal:
window size 640*480
Video bytespreline = 1280
Display:
Image byte order = LSBFirst
Bitmap unit = 32
Bitmap bit order = LSBFirst
Bitmap pad = 32
Window:
Depth = 24
Red mask = 0x00ff0000
Green mask = 0x0000ff00
Blue mask = 0x000000ff
Bits per R/G/B = 8
Image byte order = LSBFirst
Bitmap unit = 32
Bitmap bit order = LSBFirst
Bitmap pad = 32
Depth = 24
Red mask = 0x00ff0000
Green mask = 0x0000ff00
Blue mask = 0x000000ff
Bits per pixel = 32
Bytes per line = 2560
IsShared = True
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0"
after 431 requests (19 known processed) with 0 events remaining.
root#my-laptop:/home/foo/V4l2_samples-0.4.1# ./capturer_mmap -D /dev/video0 -w 640*480 -p 0 | ./viewer -w 640*480 -p 0
window size 640*480
Video bytespreline = 1280
Display:
Image byte order = LSBFirst
Bitmap unit = 32
Bitmap bit order = LSBFirst
Bitmap pad = 32
Window:
Depth = 24
Red mask = 0x00ff0000
Green mask = 0x0000ff00
Blue mask = 0x000000ff
Bits per R/G/B = 8
Image byte order = LSBFirst
Bitmap unit = 32
Bitmap bit order = LSBFirst
Bitmap pad = 32
Depth = 24
Red mask = 0x00ff0000
Green mask = 0x0000ff00
Blue mask = 0x000000ff
Bits per pixel = 32
Bytes per line = 2560
IsShared = True
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0"
after 101 requests (19 known processed) with 0 events remaining.
I have no idea how to fix this. I belive the probrem is in C code because I can to use webcam with Webcam Chesse application. Any help is very appreciated. Thanks a lot!
it looks like you are displaying the image in a completely wrong format.
when working with v4l2, you should definitely check out "libv4l" (packaged in debian, so also available in ubuntu). v4l2 allows a device to output it's frames in any of a very large number of video-formats, some of those are compressed (e.g. using jpeg).
core v4l2 does not provide any means to convert the image into a given format your application supports, so in theory your application must support all possible formats.
in order to avoid code duplication (each v4l2-capable application faces the same problem!), libv4l was created: it allows low-level access to the device, but at the sametime guarantees that the frame can be access using a few standard formats.
e.g. if the device only supports jpeg-output and your app requests RGB32 frames, libv4l will transparently convert for you.
you can even use libv4l with some LD_PRELOAD tricks, in order to make it work with applications that have been compiled without libv4l-support (just to check whether my suggestion makes sense)

Resources