In order to boot a Linux kernel on an embedded device I have to tag the kernel with a special header. The program used to tag the kernel is provided by the manufacture of the device as a 32-bit binary only. This is very annoying as I have to install hundreds of megabytes libraries on my 64-bit system only to tag a kernel with few bytes. This is how the kernel is tagged:
$./mkimage -f kernel.cfg -d zImage_without_header zImage
kernel.cfg:
##########################################################
#ENCINFO.CFG
#
# information and command for encode the Linux zImage
##########################################################
# Magic number for the ImageHeader, use this to seach start of the Image Header
#
MAGIC_NUMBER 0x27051956
#operation system type
OS_TYPE linux
#cpu architecture type
CPU_ARCH arm
#image type
IMAGE_TYPE kernel
#compress type
COMPRESS_TYPE gzip
#
DATALOAD_ADDRESS 0x00008000
#
ENTRY_ADDRESS 0x00008000
#image name string
IMAGE_NAME kernel.img
#model name string
MODEL_NAME DNS-313
# version string
VERSION 1.00b18
# mac address string
MAC_ADDRESS FF-FF-FF-FF-FF-FF
#the beginning offset of writing header
START_OFFSET 0x00
#the end offset of writing header
END_OFFSET 0xFF
#whether overwrite
OVERWRITE n
The mkimage binary is different from the mkimage that is available from e.g. the Debian repository, that one will not work for my device. I have tried to create a 1MB file and tagged it to display the header:
$dd if=/dev/zero bs=1k count=1024 of=zImage_without_header
$./mkimage -f kernel.cfg -d zImage_without_header zImage
output from last command:
Magic Number: 27051956
Image Name: kernel.img
Created: Wed May 2 17:40:43 2012
Image Type: ARM Linux Kernel Image (gzip compressed)
Data Size: 1048576 Bytes = 1024.00 kB = 1.00 MB
Load Address: 0x00008000
Entry Point: 0x00008000
Model Name: DNS-313
Version : 1.00b18
Mac Address: ff:ff:ff:ff:ff:ff
$hexdump -C zImage
output from last command:
00000000 27 05 19 56 [2c 83 53 d5] 4f a1 [55 7b 00 10 00 00] |'..V,.S.O.U{....|
00000010 00 00 80 00 00 00 80 00 [a7 38 ea 1c] 05 02 02 01 |.........8......|
00000020 6b 65 72 6e 65 6c 2e 69 6d 67 00 00 00 00 00 00 |kernel.img......|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 44 4e 53 2d 33 31 33 00 00 00 00 00 00 00 00 00 |DNS-313.........|
00000050 31 2e 30 30 62 31 38 00 00 00 00 00 00 00 00 00 |1.00b18.........|
00000060 ff ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00 |................|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00100060
The kernels should always be tagged with a header like the one above as I do not need to change anything. The the values enclosed in brackets [] seem to change when the filesize does, but I do not know how.
I think that the same thing could be accomplished with a small C program, but I am not sure where to start and how?
Any suggestions or ideas are welcome.
It might be a long shot, but if you do not have access to the "mkimage" source code, you can try disassembling it with objdump and try to figure out what is going on :
$ objdump -d ./mkimage
Related
I've been banging my head against the wall in an attempt to understand why the following assembly is not correctly dumping the contents of 'HELLO_WORLD'.
; Explicitly set 16-bit
[ BITS 16 ]
[ ORG 0x7C00 ]
; Create label for hello world string terminated by null.
HELLO_WORLD db 'hello world', 0
start:
; Move address of HELLO_WORLD into si
mov SI, HELLO_WORLD
call print_string
; Continue until the end of time
jmp $
print_string:
loop:
; Retrieve value stored in address at si
mov al, [SI]
mov ah, 0x0E
cmp al, 0
; Finish execution after hitting null terminator
je return
INT 0x10
; Increment contents of si (address)
inc SI
jmp loop
return:
ret
; boot loader length *must* be 512 bytes.
times 510-($-$$) db 0
dw 0xAA55
In the end, I discovered that if we do not execute (make it not code) the label, then it functions correctly.
jmp start
HELLO_WORLD db 'hello world',0
The part I find the most confusing, looking at the hex dump, HELLO_WORLD is still in the binary (at the beginning - and there appears to be no distinction of its type).
cat nojmp_boot.out
00000000 68 65 6c 6c 6f 20 77 6f 72 6c 64 00 be 00 7c e8 |hello world...|.|
00000010 02 00 eb fe 8a 04 b4 0e 3c 00 74 05 cd 10 46 eb |........<.t...F.|
00000020 f3 c3 eb e8 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
00000200
cat jmpboot.out
00000000 eb 22 68 65 6c 6c 6f 20 77 6f 72 6c 64 00 be 02 |."hello world...|
00000010 7c e8 02 00 eb fe 8a 04 b4 0e 3c 00 74 05 cd 10 ||.........<.t...|
00000020 46 eb f3 c3 eb e8 00 00 00 00 00 00 00 00 00 00 |F...............|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
00000200
Inspecting the first two bytes, we can see 'e8 22' is a shortjump to address 22 (http://net.cs.uni-bonn.de/fileadmin/user_upload/plohmann/x86_opcode_structure_and_instruction_overview.pdf).
My question is:
Why can we not have 'HELLO_WORLD' as a part of the execution of the program, as far I was concerned, there was no distinction between code and data?
I'm using the following for compilation:
nasm -f bin -o boot.bin boot.asm && if [ $(stat -c "%s" boot.bin) -ne 512 ]; then x; fi && qemu-system-x86_64 boot.bin
Execution starts at the top. If you omit the jmp start then the character h will get interpreted by the CPU as if it were an instruction. Surely you see that such can not be correct?
as far I was concerned, there was no distinction between code and data?
There's no distinction between code and data when we consider their placement in the binary. But code and data still remain 2 completly different items. Code being the only one that can get executed by the CPU.
Since you're creating a boot sector the execution begins at the first byte of the generated file. It won't begin at the start label or anywhere else. Since the string "hello world" is at the start of the file these bytes are what get executed first. These bytes are interpreted by the CPU as instructions, not characters, and they get executed as whatever instructions they get decoded as.
Here are the instructions that get executed:
7c00: 68 65 6c push 0x6c65
7c03: 6c ins BYTE PTR es:[di],dx
7c04: 6f outs dx,WORD PTR ds:[si]
7c05: 20 77 6f and BYTE PTR [bx+0x6f],dh
7c08: 72 6c jb 0x7c76
7c0a: 64 00 be 00 7c add BYTE PTR fs:[bp+0x7c00],bh
7c0f: e8 02 00 call 0x7c14
7c12: eb fe jmp 0x7c12
7c14: 8a 04 mov al,BYTE PTR [si]
...
I load a rootfs image into RAM via u-boot tftp and flash it to the device flash storage. This is currently done manually, but now I want to do it automatically via a u-boot script:
tftp ${rootfs_image};
mmc write ${loadaddr} ${blk} ${cnt}
However, when it looks for an image from the tftp server with the u-boot tftp ${rootfs_image} command and it DOESN'T find the image, I don't want to run the mmc write part of the script.
How do I check if the tftp command successfully downloaded the image into RAM?
Using the TFTP protocol does not ensure that the integrity of the transferred data will be preserved - see section Security Consideration in this article.
Assuming your u-boot has the hash command available, or that you can re-compile it with CONFIG_CMD_HASH=y, you could use an SHA-256 hash for verifying that your image was properly transferred:
On a Linux TFTP server:
# create an image for the purpose of the example
echo "Binary Image" > image.bin
# display sha256 hash for image.bin
sha256sum -b image.bin
36949f85f1bff0d5d1dd5fcfdfd725e919b0ee64be24f7f3ccfb53908fd09550 *image.bin
# create a file containing the hash in binary
# credits:
sha256sum -b image.bin | xxd -r -p > image.bin.sha256sum.bin
# display content of binary file
hexdump -C image.bin.sha256sum.bin
00000000 36 94 9f 85 f1 bf f0 d5 d1 dd 5f cf df d7 25 e9 |6........._...%.|
00000010 19 b0 ee 64 be 24 f7 f3 cc fb 53 90 8f d0 95 50 |...d.$....S....P|
00000020
On your u-boot system (using the memory layout available on my Alwinner H5 system here):
# 0x40080000: address where image.bin will be transfered
# 0x40090000: address where image.bin.sha256sum.bin will be transfrered
# 0x40090000: address where the sha256 has will be computed by u-boot on the 13 bytes of image.bin
# clearing memory
mw.b 0x40080000 0 0x2000
mw.b 0x40090000 0 0x20
mw.b 0x400A0000 0 0x20
md.b 0x40080000 0x20
40080000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
40080010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
md.b 0x40090000 0x20
40090000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
40090010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
md.b 0x400A0000 0x20
400a0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
400a0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
tftp 0x40080000 image.bin
Using ethernet#1c30000 device
TFTP from server 192.168.1.22; our IP address is 192.168.1.2
Filename 'image.bin'.
Load address: 0x40080000
Loading: #
5.9 KiB/s
done
Bytes transferred = 13 (d hex)
tftp 0x40090000 image.bin.sha256sum.bin
Using ethernet#1c30000 device
TFTP from server 192.168.1.22; our IP address is 192.168.1.2
Filename 'image.bin.sha256sum.bin'.
Load address: 0x40090000
Loading: #
15.6 KiB/s
done
Bytes transferred = 32 (20 hex)
md.b 0x40090000 0x20
40090000: 36 94 9f 85 f1 bf f0 d5 d1 dd 5f cf df d7 25 e9 6........._...%.
40090010: 19 b0 ee 64 be 24 f7 f3 cc fb 53 90 8f d0 95 50 ...d.$....S....P
hash sha256 0x40080000 0x0d *0x400A0000
sha256 for 40080000 ... 4008000c ==> 36949f85f1bff0d5d1dd5fcfdfd725e919b0ee64be24f7f3ccfb53908fd09550
cmp.b 0x40090000 0x400A0000 0x20
Total of 32 byte(s) were the same
echo $?
0
In the case image.bin and/or image.bin.sha256sum.bin would have been improperly transferred, the chances that the computed sha256 would match the transferred one are extremely unlikely - using SHA-512 would make this even more unlikely.
The outcome would have been in the case of an incorrect transfer:
echo $?
1
In real life, this would be more practical to transfer an image with a fixed, maximum length, for example padded with zeroes, so that a u-boot script responsible for validating the transferred image would use a fixed length, say 8 KiB, that is 0x2000 bytes.
ls -lgG image.bin
-rw-rw-r-- 1 13 Dec 17 20:34 image.bin
dd if=/dev/zero of=image.bin bs=8K count=1 oflag=append
ls -lgG image.bin
-rw-rw-r-- 1 8192 Dec 17 21:03 image.bin
hexdump -C image.bin
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00002000
The correct u-boot command to use for computing the hash would be:
hash sha256 0x40080000 0x2000 *0x400A0000
And a new binary file containing the new hash would of course have to be created as well:
sha256sum -b image.bin | xxd -r -p > image.bin.sha256sum.bin
I used two files for the purpose of the example, but you could just append image.bin.sha256sum.bin to image.bin and transfer one single file.
You would have to replace 0x400A0000 by 0x40082000 in the hash and cmp commands.
I hope this helps.
The tftp command returns true if it succeeds. So you could write:
tftp ${rootfs_image} && mmc write ${loadaddr} ${blk} ${cnt}
Now mmc write will only be executed if the tftp command succeeds.
I am trying to craft a linker-command script to be bootable by legacy grub (using multiboot). I am having difficulty getting the multiboot header in the required location (within the first 8192 bytes). My script looks something like:
SECTIONS
{
.multiboot :
{
__multiboot_header = .;
*(.multiboot)
}
.text 0x00100000 :
{
*(.text*)
*(.rodata)
}
/* ... remainder of script ... */
}
Overall, my objective is to have my custom executable loaded by the bootloader after the first 1MiB of physical memory; the address as part of the .text section declaration seems to have done this as I expected. Reading the ELF header gives the entry point as:
$ readelf -h kernel.elf | grep Entry
Entry point address: 0x100000
However, in doing so I seem to have also increased the file by this much.
$ ls -l file.elf
-rwxr-xr-x 1 user user 1049960 May 13 02:20 file.elf
The area between the ELF header and the .text section is initialized to zeros.
$ hexdump -C file.elf
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 03 00 01 00 00 00 00 00 10 00 34 00 00 00 |............4...|
00000020 00 04 10 00 00 00 00 00 34 00 20 00 02 00 28 00 |........4. ...(.|
00000030 09 00 08 00 01 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 00 00 00 00 f8 00 10 00 f8 f0 4e 00 07 00 00 00 |..........N.....|
00000050 00 00 20 00 51 e5 74 64 00 00 00 00 00 00 00 00 |.. .Q.td........|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................|
00000070 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00100000 8b 25 f8 f0 4e 00 50 53 e8 66 00 00 00 fa f4 eb |.%..N.PS.f......|
00100010 fc 55 89 e5 53 83 ec 10 c7 45 f8 00 00 00 00 eb |.U..S....E......|
00100020 38 a1 f4 00 10 00 8b 55 f8 01 d2 01 d0 8b 15 f4 |8......U........|
Also, although readelf -s reports that __multiboot_header has a value of 0x0 (which should be the address of the structure since it was defined at the same point it was mentioned in the linker file, right?):
$ readelf -s kernel.elf | grep multiboot
22: 00000000 0 NOTYPE GLOBAL DEFAULT 1 __multiboot_header
The output of readelf -S seems to conflict:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 1] .multiboot PROGBITS 00000000 1000f8 00000c 00 0 0 1
[ 2] .text PROGBITS 00100000 100000 000096 00 AX 0 0 1
Which implies that the .multiboot section is actually inside the .text section.
If I offset into the file by 0x1000f8 then I can find the structure, however, I am not sure where the offset came from.
tl;dr
1) How can I ensure a specific data structure is within the first 8192 bytes of the output file?
2) How can I specify the load address without inflating the output binary with large gaps of zero-initialized blocks?
The elf file format is generated by its own rules, how it stores the information is not directly influenced by the linker file (e.g. at what offsets the sections are stored must not correlate with their location at lifetime in memory). It's the memory layout which is described by the SECTIONS command in your linker file, and the elf file format describes this layout... You need a elf capable loader to load the individual sections into the target locations.
To get a flat binary file which can be loaded 1:1 into memory, use objcopy (e.g. something like objcopy -O binary myfile.elf myfile.bin). The layout of that file is directly influenced by your linker script, and the content of the .multiboot section should be really at offset 0.
I've got an image file of a hard drive from a client that wants a database extracted out of it. The client does not know any details except that the database was once installed on the server from which the image was created.
I found out that it is a UNIX system with a Informix DBS installed, but I am unable to find any database files. I'm not sure about the version of Informix, but it seem that it was installed around 15 years ago.
I'm not able to boot from the image. I'm just viewing the files.
Do informix database files have an extension and what could it be? Any other tips how to identify the database files?
Do you know whether the database was Informix Standard Engine (SE) or Informix (Informix Dynamic Server — IDS — or one of its multitude of namesakes over the years)?
Standard Engine
If it was SE, then the database files are in a directory database.dbs and the files holding the indexes and data for the tables have extensions .idx and .dat. That's pretty much fixed and very easy. The files and the directory should belong to group informix; the owner will be whoever created the database or the table within the database.
Informix Dynamic Server
If it was IDS, then there is no guaranteed naming convention, and Informix didn't even recommend one. Depending on the state of the disk, I'd look for large files that are owned by user informix and belong to group informix and have 660 (-rw-rw----) permissions. The files will have structure, but it isn't easy to discern it.
For example, I have 'chunk 0 of the root dbspace' in a file toru_31.rootdbs.c0 (server name toru_31 — a naming standard I imposed on my systems). It starts with:
0x0000: 00 00 00 00 01 00 AB 89 03 00 00 18 30 01 C0 06 ............0...
0x0010: 00 00 00 00 00 00 00 00 49 42 4D 20 49 6E 66 6F ........IBM Info
0x0020: 72 6D 69 78 20 44 79 6E 61 6D 69 63 20 53 65 72 rmix Dynamic Ser
0x0030: 76 65 72 20 43 6F 70 79 72 69 67 68 74 20 32 30 ver Copyright 20
0x0040: 30 31 2C 20 32 30 31 31 20 20 49 42 4D 20 43 6F 01, 2011 IBM Co
0x0050: 72 70 6F 72 61 74 69 6F 6E 2E 00 00 00 00 00 00 rporation.......
0x0060: 00 00 00 00 00 00 00 00 00 00 03 00 00 08 00 00 ................
0x0070: BA 2D CC 50 1A 00 00 00 00 00 00 00 C8 00 00 00 .-.P............
0x0080: 31 31 37 33 05 00 00 00 00 00 00 00 00 00 00 00 1173............
0x0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
However, 'chunk 1 of the root dbspace' (file toru_31.rootdbs.c1) starts:
0x0000: 00 00 00 00 02 00 F1 C6 00 00 00 18 18 00 E4 07 ................
0x0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
* (125)
0x07F0: 00 00 00 00 00 00 00 00 00 00 00 00 61 C6 92 00 ............a...
0x0800: 69 6E 66 6F 72 6D 69 78 69 6E 66 6F 72 6D 69 78 informixinformix
* (127)
0x1000: 02 00 00 00 02 00 BE B6 06 00 08 08 20 00 D8 07 ............ ...
0x1010: 00 00 00 00 00 00 00 00 10 06 00 00 01 00 00 00 ................
0x1020: EA 06 00 00 03 00 00 00 75 08 00 00 08 00 00 00 ........u.......
0x1030: A1 08 00 00 08 00 00 00 B5 0A 00 00 30 03 00 00 ............0...
There is very little information there to give the game away. Although the appearance of informix (128 lines containing informix twice) looks like a tell-tale sign, it isn't — I created the chunk with a program that writes informix over the disk space. It simply shows where the server has not yet written data to this chunk.
You can look for $INFORMIXDIR. In fact, if there's a directory /INFORMIXTMP, you can look in the text file /INFORMIXTMP/.infxdirs to see where Informix has been installed. From those directories, you can look in $INFORMIXDIR/etc for onconfig files - they're text files that contain an entry ROOTPATH, which is the pathname of chunk 0 of the root dbspace — basically, the starting point for the whole system. There's usually an onconfig.std which is a template; the naming convention is not firmly fixed, though I always use onconfig.servername (so the config file for toru_31 is onconfig.toru_31). You may also find other files around in $INFORMIXDIR/etc. For example, there's a file oncfg_toru_31.31 (prefix oncfg_, followed by server name toru_31 followed by dot and the server number 31) which contains information about the chunks and other disk space etc used by the server. You might also see binary files analogous to .conf.toru_31 and .infos.toru_31 — the .infos file is normally present only while the server is up but the .conf file persists. These files have some limited information in them, most notably the name of the onconfig file.
If you can find these files on the disk, then you can proceed to identify where the data was stored on the disk.
I have been using SQL for like 10 years but now I realised I never knew how the client actually receive and process data it gets from the server.
My question is, how does the result from Microsoft SQL Server actually look like in raw format? The same as that result from HTTP server contains HTTP headers and a Content-Type header to tell what the body format is (mostly HTML for web pages).
The protocol name is TDS (Tabular Data Stream).
Some documentation is available at MSDN.
There is a very basic example of data being transferred for simple query select 'foo' as 'bar'
Request
Packet header (type, legth, etc)
01 01 00 5C 00 00 01 00
Packet data
16 00 00 00 - headers total length
12 00 00 00 - first header length
02 00 - type
00 00 00 00 00 00 00 01 00 00 00 00 - data
0A 00 73 00 65 00 6C 00 65 00 63 00 74 00 20 00
27 00 66 00 6F 00 6F 00 27 00 20 00 61 00 73 00
20 00 27 00 62 00 61 00 72 00 27 00 0A 00 20 00
20 00 20 00 20 00 20 00 20 00 20 00 20 00 - sql
Response
Packet header (type, legth, etc)
04 01 00 33 00 00 01 00
Packet data
columns metadata
81 - record id
01 - count
first column
00 00 00 00 00 - user type
20 00 - flags
A7 - type
03 00 - length
09 04 D0 00 34 - colation
03 - column name length
62 00 61 00 72 00 - column name bytes
rows
D1 - record id
03 00 - length
66 6F 6F - value
ending data
FD - record id
10 00 - status
C1 00
01 00 00 00 00 00 00 00 - rows total
We can also look at parser implementation thanks to reference sources.