Print arbitrary hex characters in u-boot shell - u-boot

I'd like colorize my u-boot bootcmd so it prints a breathtaking error message. Normally I'd just use ANSI escape sequences such as below.
#!/bin/bash
printf '\x1b[31mERROR\33[0m'
#!/usr/bin/env python
print("\x1b[31mERROR\33[0m")
How can get equivalent behavior in u-boot? It seems u-boot will just remove the backslash such as below
# u-boot shell
echo \33[31m # prints "33[31m"
echo \x1b[31m # prints "x1b[31m"

On a bash console you can use CTRL-V to enter a control character verbatim. This is not supported by U-Boot yet. But I have submitted a patch to enable this, cf. https://patchwork.ozlabs.org/project/uboot/list/?series=152686.
U-Boot's echo command does not know '\x' escape sequences but copies an escape character verbatim to the console.
So this is what you can do:
Create a script test.txt with your echo commands which contains the escape sequences.
echo -e 'echo \e[33mError\e[37m\necho \e[32mWarning\e[37m' > test.txt
I show it below in hexadecimal format so it becomes obvious what is in the file:
00000000 65 63 68 6F 20 1B 5B 33 33 6D 45 72 echo .[33mEr
0000000C 72 6F 72 1B 5B 33 37 6D 0A 65 63 68 ror.[37m.ech
00000018 6F 20 1B 5B 33 32 6D 57 61 72 6E 69 o .[32mWarni
00000024 6E 67 1B 5B 33 37 6D 0A ng.[37m.
Convert this to a U-Boot image
mkimage -T script -n 'test' -d test.txt test.scr
In U-Boot load the script. I did this using tFTP:
dhcp $script_addr_r test.scr
Now you can execute the script
source $script_addr_r
When U-Boot is build with CONFIG_DISTRO_DEFAULTS=y it will look for scripts boot.scr.uimg and boot.scr on your boot device. So this is probably where you want to integrate the escape sequences.

Related

Weird behavior of hexdump on MacOS

I am supposed to recreate the behavior of hexdump in C and now when I (almost) finished the task, the actual hexdump command behaves weird.
When I use:
hexdump -C filename1 notexistingfilename2
the error message for the non existing file appears between the lines of the output of the first file.
like this:
0000c4f0 65 00 64 79 6c 64 5f 73 74 75 62 5f 62 69 6e 64 |e.dyld_stub_bind|
0000c500 65 72 00 5f 5f 64 79 6c 64 5f 70 72 69 76 61 74 |er.__dyld_privat|
hexdump: h: No such file or directory
0000c510 65 00 00 00 00 00 00 00 |e.......|
0000c518
h being the non existing file.
This wasn't the case when I used hexdump earlier today. (System is MacOS and the behavior is the same in Bash aswell as in zsh, also not using the -C flag doesn't make a difference).

Why can the wmic data from a text file not be processed because of some weird character coding problem?

I've been working on a little script that determines which disk is usable in our specific system. There has to be basically less than 1 TB of space on the disk in order to be considered as usable.
This is the complete code:
#echo off
chcp 65001>nul
setlocal enabledelayedexpansion
wmic logicaldisk get caption,freespace>c:\cmd\1\getDiskInfo.txt
for /f "tokens=1,2 eol=C" %%I in (C:\cmd\1\getDiskInfo.txt) do (
set diskCaption=%%I
set diskFreeSpace=%%J
set captionFreeSpace=!diskCaption! !diskFreeSpace!
for /f "tokens=1,2 delims= " %%X in ("!captionFreeSpace!") do (
if [%%Y] neq [] set usedDisks=%%X %%Y
for /f "tokens=1,2 delims= " %%A in ("!usedDisks!") do (
set freeSpaceFirstChar=%%B
set /a freeSpaceFirstChar=!freeSpaceFirstChar:~0,1!
if !freeSpaceFirstChar! gtr 1 set usableDisk=%%A
)
)
)
echo %usableDisk%
pause
But the output I get for %usableDisk% is always ECHO is off. which means that %usableDisk% does not even exist. I've done a little investigation and from my understanding it's because of a character coding related problem. I've copied the content of getDiskInfo.txt to another .txt file, and the batch file managed to give me the right output with that text file created by me.
The contents of getDiskInfo.txt and the other text file was both:
Caption FreeSpace
A:
B: 1098552672256
C: 40824201216
D:
E: 1042498560000
F: 40222941184
The output of the original script created file was ECHO is off.. The output with the text file created by me was F: which is the correct output because we can't use the system drive C:.
So I tried echo END OF FILE>>getDiskInfo.txt and it added the line 久⁄䙏䘠䱉൅ to the script created file, but the same command added END OF FILE to my text file. I'm completely lost on this one.
Do you have any suggestions or probable solutions?
There are multiple problems to solve for this task to get the drive letter of a (local) hard disk drive with less than one TiB (1 099 511 627 776 bytes) free space which is not the system drive.
1. Character encoding of WMIC output
WMIC outputs data always with character encoding UTF-16 Little Endian with byte order mark abbreviated as UTF-16LE+BOM.
So the data output
Caption FreeSpace
A:
B: 1098552672256
C: 40824201216
D:
E: 1042498560000
F: 40222941184
is as byte stream with byte offset left to : and ASCII representation right to ;:
0000h: FF FE 43 00 61 00 70 00 74 00 69 00 6F 00 6E 00 ; ÿþC.a.p.t.i.o.n.
0010h: 20 00 20 00 46 00 72 00 65 00 65 00 53 00 70 00 ; . .F.r.e.e.S.p.
0020h: 61 00 63 00 65 00 20 00 20 00 20 00 20 00 20 00 ; a.c.e. . . . . .
0030h: 20 00 0D 00 0A 00 41 00 3A 00 20 00 20 00 20 00 ; .....A.:. . . .
0040h: 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 ; . . . . . . . .
0050h: 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 ; . . . . . . . .
0060h: 20 00 20 00 20 00 0D 00 0A 00 42 00 3A 00 20 00 ; . . .....B.:. .
0070h: 20 00 20 00 20 00 20 00 20 00 20 00 31 00 30 00 ; . . . . . .1.0.
0080h: 39 00 38 00 35 00 35 00 32 00 36 00 37 00 32 00 ; 9.8.5.5.2.6.7.2.
0090h: 32 00 35 00 36 00 20 00 20 00 0D 00 0A 00 43 00 ; 2.5.6. . .....C.
00a0h: 3A 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 ; :. . . . . . . .
00b0h: 34 00 30 00 38 00 32 00 34 00 32 00 30 00 31 00 ; 4.0.8.2.4.2.0.1.
00c0h: 32 00 31 00 36 00 20 00 20 00 20 00 20 00 0D 00 ; 2.1.6. . . . ...
00d0h: 0A 00 44 00 3A 00 20 00 20 00 20 00 20 00 20 00 ; ..D.:. . . . . .
00e0h: 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 ; . . . . . . . .
00f0h: 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 ; . . . . . . . .
0100h: 20 00 0D 00 0A 00 45 00 3A 00 20 00 20 00 20 00 ; .....E.:. . . .
0110h: 20 00 20 00 20 00 20 00 31 00 30 00 34 00 32 00 ; . . . .1.0.4.2.
0120h: 34 00 39 00 38 00 35 00 36 00 30 00 30 00 30 00 ; 4.9.8.5.6.0.0.0.
0130h: 30 00 20 00 20 00 0D 00 0A 00 46 00 3A 00 20 00 ; 0. . .....F.:. .
0140h: 20 00 20 00 20 00 20 00 20 00 20 00 34 00 30 00 ; . . . . . .4.0.
0150h: 32 00 32 00 32 00 39 00 34 00 31 00 31 00 38 00 ; 2.2.2.9.4.1.1.8.
0160h: 34 00 20 00 20 00 20 00 20 00 0D 00 0A 00 ; 4. . . . .....
But Windows command processor expects a one byte per character encoding using the code page as output on running in an opened command prompt window the command chcp. The code page depends on which country is configured for the account used to run the command process processing the batch file.
The command line chcp 65001>nul to change to Unicode encoding UTF-8 is of no help here.
Processing UTF-16LE encoded output with FOR directly cause troubles as documented on Stack Overflow multiple times, see for example How to correct variable overwriting misbehavior when parsing output?
A solution would be to redirect the output of WMIC into a temporary file, output this temporary file to handle STDOUT (standard output) of a command process started in background with %ComSpec% /c using the command TYPE with capturing this output by the command process executing the batch file, process this ASCII output line by line, and finally delete the temporary file.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
%SystemRoot%\System32\wbem\wmic.exe LOGICALDISK GET Caption,FreeSpace >"%TEMP%\%~n0.tmp"
if not exist "%TEMP%\%~n0.tmp" goto EndBatch
for /F "skip=1 tokens=1,2" %%I in ('type "%TEMP%\%~n0.tmp"') do echo %%I %%J
del "%TEMP%\%~n0.tmp"
:EndBatch
endlocal
In this case FOR processes the ASCII byte stream:
000h: 43 61 70 74 69 6F 6E 20 20 46 72 65 65 53 70 61 ; Caption FreeSpa
010h: 63 65 20 20 20 20 20 20 0D 0A 41 3A 20 20 20 20 ; ce ..A:
020h: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ;
030h: 20 20 0D 0A 42 3A 20 20 20 20 20 20 20 31 30 39 ; ..B: 109
040h: 38 35 35 32 36 37 32 32 35 36 20 20 0D 0A 43 3A ; 8552672256 ..C:
050h: 20 20 20 20 20 20 20 34 30 38 32 34 32 30 31 32 ; 408242012
060h: 31 36 20 20 20 20 0D 0A 44 3A 20 20 20 20 20 20 ; 16 ..D:
070h: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ;
080h: 0D 0A 45 3A 20 20 20 20 20 20 20 31 30 34 32 34 ; ..E: 10424
090h: 39 38 35 36 30 30 30 30 20 20 0D 0A 46 3A 20 20 ; 98560000 ..F:
0a0h: 20 20 20 20 20 34 30 32 32 32 39 34 31 31 38 34 ; 40222941184
0b0h: 20 20 20 20 0D 0A ; ..
But it is in general always better to avoid the usage of a temporary file as there is never the guarantee that the temporary file can be created at all during the execution of the batch file.
2. System drive is not always C:
Windows is installed by default on drive C: and so the system drive is C:. But Windows can be installed also to a different drive in which case the system drive is not C:. Any code depending on default data instead of using the appropriate data is a not good written code.
There is predefined the Windows environment variable SystemDrive with the drive letter and the colon of the drive on which active Windows is installed. The environment variable SystemRoot contains the path to the Windows directory which contains the directory System32 with all executables from the Windows Commands list which are not internal commands of cmd.exe.
All those system environment variables can be seen with their values on opening a command prompt window and running set system. Running just set outputs all environment variables with their values defined for the current user account.
3. Integer value range is limited to 32-bit signed integer
The Windows command processor cmd.exe uses always only 32-bit signed integer on evaluation of an arithmetic expression with set /A and for comparing integer values with command IF on using the operators EQU, NEQ, LSS, LEQ, GTR, GEQ.
Therefore the integer value range is −2147483648 to 2147483647. So maximum is one byte less than 2 GiB. The value is 1099511627776 requires 64-bit integer value range not supported by cmd.exe.
BTW: if [%%Y] neq [] is never a good comparison because of [ and ] have no special meaning for Windows command processor and neq results here first in the approach to convert the left string into a 32-bit signed integer value which fails because of [ is an invalid character for an integer value and therefore running next a string comparison with condition being true if the string comparison returns not 0, i.e. the compared strings are not equal. Better would be if not "%%Y" == "" which runs directly and more safely a string comparison on not equal strings. See Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files for details on how command IF executes a string comparison.
Solution to get drives with less than one TiB free space
It is a good idea to read the documentation of a class of which properties are accessed using the Windows Management Instrumentation Command-line utility. This is here the Win32_LogicalDisk class.
There is in addition to FreeSpace of type uint64 and DeviceID of type string instead of Caption perhaps also useful the property DriveType of type uint32 to filter out drives of wrong type in addition to drives with too much free space and the system drive by using a where clause on wmic execution.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "UsableDrive="
for /F "skip=1 tokens=1,2" %%I in ('""%SystemRoot%\System32\wbem\wmic.exe" LOGICALDISK where (DriveType=3 and FreeSpace^<1099511627776 and DeviceID!='C:') GET DeviceID,FreeSpace 2>nul"') do (
echo Drive %%I has %%J free bytes.
if not defined UsableDrive set "UsableDrive=%%I"
)
if defined UsableDrive echo Selected drive %UsableDrive%
endlocal
Important to know here is that FOR starts in background with %ComSpec% /c one more command process with the command line specified within ' appended as additional arguments. For that reason the command line with WMIC must fulfill the Windows command processor requirements described by help output on running cmd /? in a command prompt window on being in total three times parsed.
The first parsing is done by cmd.exe processing the batch file before executing command FOR.
The second parsing is done by cmd.exe instance on starting it in background by the cmd.exe instance processing the batch file with the following command line on Windows installed to C:\Windows.
C:\Windows\System32\cmd.exe /c ""C:\WINDOWS\System32\wbem\wmic.exe" LOGICALDISK where (DriveType=3 and FreeSpace^<1099511627776 and DeviceID!='C:') GET DeviceID,FreeSpace 2>nul"
The third parsing is done by the background command process before executing wmic.exe. The operator < in where clause must be interpreted as literal character and not as redirection operator which is the reason why < is escaped with ^ to run wmic.exe finally with:
"C:\Windows\System32\wbem\wmic.exe" LOGICALDISK where (DriveType=3 and FreeSpace<1099511627776 and DeviceID!='C:') GET DeviceID,FreeSpace
WMIC filters out with DriveType=3 all network drives, floppy disk drives, CD and DVD drives and other removable drives, RAM disks, etc. Hard disks connected to the computer using an external USB port or an eSATA port are not filtered out because of those drives have also value 3 for the drive type. Windows cannot determine if a hard disk is mounted inside the casing of the computer or outside. So a local hard disk is any hard disk connected to the computer, internal and external hard disks.
The system drive is filtered out with second condition DeviceID!='%SystemDrive%'.
The last condition FreeSpace<1099511627776 results in ignoring all drives with 1 TiB or more free space.
So the list is reduced already to those drives which fulfill all three conditions.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
cmd /?
del /?
echo /?
endlocal /?
for /?
goto /?
if /?
set /?
setlocal /?
type /?
wmic /?
wmic logicaldisk /?
wmic logicaldisk get /?
See also the Microsoft article about Using command redirection operators for an explanation of > and 2>nul.
If I understand your requirements correctly, the following, much shorter, single line batch-file, should output only the usable drives, i.e. which, are not your system drive, and have less than 1 TB of free disk space.
#(For /F "Tokens=1-2" %%G In ('""%__AppDir__%wbem\WMIC.exe" LogicalDisk Where (DeviceID !='%SystemDrive%' And FreeSpace ^<'1000000000000') Get DeviceID,FreeSpace 2>NUL|"%__AppDir%find.exe" ":""')Do #Set "_= %%H"&SetLocal EnableDelayedExpansion&Echo %%G !_:~-14!&EndLocal)&Pause
As you did not explain in your question, what you were doing with the data retrieved, I have simply printed them to the console window in a similar format to your original getDiskInfo.txt, (I even right aligned the bytes column just for fun!).

Which compiler, compiled this file?

I am using gnu gcc and armcc to compile a few C files. How can I get the information about which compiler compiled which file?
Ex: test.cpp is being compiled by armcc or gnu gcc.
The makefile is very complicated and I am looking out for a command by which I can check which compiler compiled which file.
Any ideas?
Sometimes you can look at the file with a hex editor and tell if the compiler wrote its name into the file.
I'm not sure if there's an easier way, but you can find it embedded in the binary with gcc (at least on my platform):
$ hexdump -C foo | grep -A2 GCC
00001030 00 00 00 00 00 00 00 00 47 43 43 3a 20 28 55 62 |........GCC: (Ub|
00001040 75 6e 74 75 2f 4c 69 6e 61 72 6f 20 34 2e 37 2e |untu/Linaro 4.7.|
00001050 32 2d 32 32 75 62 75 6e 74 75 33 29 20 34 2e 37 |2-22ubuntu3) 4.7|
Some compiler embedd compiler name and version in to the binrary, but not all. We can also embedd whatever information we want into the binary.
gcc -DCOMPILER_DETAILS='"gcc 4.3.3"' temp.c
In temp.c use the macro COMPILER_DETAILS in any place, like just use it in printf. So that this string literal will be embedd in the generated binary file. Dont assign this string to unused variable, compiler will not embedd because of optimization.

How can i export file from wireshark to display not in hex format

Im tring to export file from wireshark , so i could search in it.
now every option i try doesn't give simple raw format as the tcp raw view , when i follow
tcp stream .
all it gives me is hex view of the packets and the string in this kind of format breaks and can't be searchable . i want it to export to searchable format.
can it be done ?
this is what im getting now :
0000 48 54 54 50 2f 31 2e 31 20 35 30 30 20 49 6e 74 HTTP/1.1 500 Int
0010 65 72 6e 61 6c 20 53 65 72 76 65 72 20 45 72 72 ernal Server Err
0020 6f 72 0d 0a 44 61 74 65 3a 20 54 68 75 2c 20 31 or..Date: Thu, 1
0030 30 20 4e 6f 76 20 32 30 31 31 20 31 36 3a 33 32 0 Nov 2011 16:32
0040 3a 35 37 20 47 4d 54 0d 0a 50 72 61 67 6d 61 3a :57 GMT..Pragma:
0050 20 6e 6f 2d 63 61 63 68 65 0d 0a 43 6f 6e 74 65 no-cache..Conte
What about using TShark, sed and tr?
tshark -r Clmt_04.pcap -x -R "frame.number<40" | sed 's/^.{56}//' | tr -d '\n' > Clmt-04.txt
tshark -x
add output of hex and ASCII dump (Packet Bytes)
sed 's/^.{56}//'
remove the first 56 characters of each line
tr -d '\n'
remove new line character
Hope this helps
After you identify the tcp stream, you can use the following command with tshark:
tshark -nr <file>.pcapng -q -z follow,tcp,ascii,XXXX
Where XXXX is the tcp stream.

Understanding the `ctags -e` file format (ctags for emacs)

I am using "ExuberantCtags" also known as "ctags -e", also known as just "etags"
and I am trying to understand the TAGS file format which is generated by the etags command, in particular I want to understand line #2 of the TAGS file.
Wikipedia says that line #2 is described like this:
{src_file},{size_of_tag_definition_data_in_bytes}
In practical terms though TAGS file line:2 for "foo.c" looks like this
foo.c,1683
My quandary is how exactly does it find this number: 1683
I know it is the size of the "tag_definition" so what I want to know is what is
the "tag_definition"?
I have tried looking through the ctags source code, but perhaps someone better at C than me will have more success figuring this out.
Thanks!
EDIT #2:
^L^J
hello.c,79^J
float foo (float x) {^?foo^A3,20^J
float bar () {^?bar^A7,59^J
int main() {^?main^A11,91^J
Alright, so if I understand correctly, "79" refers to the number of bytes in the TAGS file from after 79 down to and including "91^J".
Makes perfect sense.
Now the numbers 20, 59, 91 in this example wikipedia says refer to the {byte_offset}
What is the {byte_offset} offset from?
Thanks for all the help Ken!
It's the number of bytes of tag data following the newline after the number.
Edit: It also doesn't include the ^L character between file tag data. Remember etags comes from a time long ago where reading a 500KB file was an expensive operation. ;)
Here's a complete tags file. I'm showing it two ways, the first with control characters as ^X and no invisible characters. The end-of-line characters implicit in your example are ^J here:
^L^J
hello.cc,45^J
int main(^?5,41^J
int foo(^?9,92^J
int bar(^?13,121^J
^L^J
hello.h,15^J
#define X ^?2,1^J
Here's the same file displayed in hex:
0000000 0c 0a 68 65 6c 6c 6f 2e 63 63 2c 34 35 0a 69 6e
ff nl h e l l o . c c , 4 5 nl i n
0000020 74 20 6d 61 69 6e 28 7f 35 2c 34 31 0a 69 6e 74
t sp m a i n ( del 5 , 4 1 nl i n t
0000040 20 66 6f 6f 28 7f 39 2c 39 32 0a 69 6e 74 20 62
sp f o o ( del 9 , 9 2 nl i n t sp b
0000060 61 72 28 7f 31 33 2c 31 32 31 0a 0c 0a 68 65 6c
a r ( del 1 3 , 1 2 1 nl ff nl h e l
0000100 6c 6f 2e 68 2c 31 35 0a 23 64 65 66 69 6e 65 20
l o . h , 1 5 nl # d e f i n e sp
0000120 58 20 7f 32 2c 31 0a
X sp del 2 , 1 nl
There are two sets of tag data in this example: 45 bytes of data for hello.cc and 15 bytes for hello.h.
The hello.cc data starts on the line following "hello.cc,45^J" and runs for 45 bytes--this also happens to be complete lines. The reason why bytes are given is so code reading the file can just allocate room for a 45 byte string and read 45 bytes. The "^L^J" line is after the 45 bytes of tag data. You use this as a marker that there are more files remaining and also to verify that the file is properly formatted.
The hello.h data starts on the line following "hello.h,15^J" and runs for 15 bytes.
The {byte_offset} for a tag entry is the number of bytes from the start of the file the function is defined in. The number before the byte offset is the line number. In your example:
hello.c,79^J
float foo (float x) {^?foo^A3,20^J
the foo function begins 20 bytes from the start of hello.c. You can verify that with a text editor that shows your cursor position in the file. You can also use the Unix tail command to display a file a number of bytes in:
tail -c +20 hello.c

Resources