Cortex M7: Branch just after start - c

I'm using the ATSAMV71Q21B MCU which uses a cortex-M7 processor. In order to add redundancy, I would like to have multiple boot loader and enter to one of those boot loader just after starting the microcontroller. Atlough, the ARM processor begins executing at the reset vector location 0x00000000. I cannot choose where I want to start.
I was wondering if it was possible to branch to one of my boot loaders using in few instructions.
For the moment, all solutions that I tried to generate hundred instructions which is too much for me. I guess that I need to manually add branch instructions the vector location 0x00000000. Although, I'm not sure where I should branch and if it is OK to do this.
Indeed, I'm not sure if I really understand the beginning of the assembly code generated. Therefore, I'm not sure where to branch.
Here is an example of the beginning of the program:
0x00400000 70 0a 40 20 d9 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 00 00 00 00 p.# Ù.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.....
0x00400020 00 00 00 00 00 00 00 00 00 00 00 00 d5 01 40 00 d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00 ............Õ.#.Õ.#.....Õ.#.Õ.#.
0x00400040 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400060 d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.....Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400080 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x004000A0 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x004000C0 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x004000E0 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400100 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 00 00 00 00 00 00 00 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.........
0x00400120 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400140 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400160 d5 01 40 00 d5 01 40 00 10 b5 05 4c 23 78 33 b9 04 4b 13 b1 04 48 af f3 00 80 01 23 23 70 10 bd Õ.#.Õ.#..µ.L#x3..K.±.H¯ó.€.##p..
0x00400180 2c 04 40 20 00 00 00 00 28 04 40 00 0c 4b 43 b1 0c 48 0d 49 10 b5 af f3 00 80 0c 48 03 68 23 b9 ,.# ....(.#..KC±.H.I.µ¯ó.€.H.h#.
0x004001A0 10 bd 0a 48 03 68 33 b9 70 47 09 4b 00 2b f7 d0 bd e8 10 40 18 47 06 4b 00 2b f5 d0 18 47 00 bf ...H.h3.pG.K.+÷Ð.è.#.G.K.+õÐ.G.¿
0x004001C0 00 00 00 00 28 04 40 00 30 04 40 20 28 04 40 00 00 00 00 00 fe e7 00 bf 16 49 17 4a 91 42 08 b5 ....(.#.0.# (.#.....þç.¿.I.J‘B.µ
If I understand correctly, this is a vector table and I should not branch here. Is that correct ?

0x00400000 70 0a 40 20 d9 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 00 00 00 00 p.# Ù.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.....
0x00400020 00 00 00 00 00 00 00 00 00 00 00 00 d5 01 40 00 d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00 ............Õ.#.Õ.#.....Õ.#.Õ.#.
0x00400040 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400060 d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.....Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400080 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
So these look fine the first one is the stack pointer load value
0x20400a70
A strange number perhaps but this part has 0x80000 bytes of ram so it is valid. so probably a linker script generated value (stack setup in the linker script rather than just start with top of ram).
Reset vector is
0x004001d9
which is properly formatted (lsbit is set) as to what it points to you have not provided.
many of the others are
0x004001d5
Also properly formatted is probably an infinite loop based on its proximity to the reset vector but who knows have to look at the code. It does not matter much for booting.
The chip/family doc indicates that user flash is at address 0x00400000 and is quite large for these parts, so both the address on the left of this dump and the reset vectors this all looks fine.
There is an indication that there is a sam-ba bootloader at some address 0x00800000 or 0x08000000 or I do not remember, you can look it up. Now I have used other Atmel parts that did not have the bootloader burned in the flash from Atmel but instead source to a sam-ba you could build and use yourself (why bother make your own much simpler less bulky), but I had issues with that approach how the flash did or didn't lock, how easy to unlock and erase, so what is the point? use SWD. This comment in the doc may indicate a burned in one in that case then you need to look at how to choose to boot that application instead of the user application, in either case since they indicate a specific address. If it is user changeable then that would be where you want to put your bootloader possibly or if fixed and not changeable then just use it as your bootloader.
As to where in general you put your bootloader that is all you, you choose your design, what you mean by bootloader, what features etc. Often misused but the term implies both booting the part but also having a way to load other applications in some way (run one in ram, reprogram the user/boot/application flash, etc). Something you need to look at is how the flash works on this device assuming you want to be able to re-write a portion of it with new firmware. Sometimes you can execute out of and flash at the same time but more likely to do that they use multiple flash banks so you can run in one and modify the other, which then leads into what is their boot scheme does it always only boot on one and never the other so you either have to keep the bootloader as-is forever or have a scheme, also have to have a scheme for choosing which of the images on which banks to be the default firmware after the bootloader boots.
These cores can run code in ram generally and no reason to expect not here (it's not the core, it's the chip vendor's implementation that matters) so doing a copy and jump of a portion of the bootloader to ram in order to not be running on flash allowing you to reprogram any of the flash but put yourself at risk if it fails or if power goes the part may be bricked.
If the chip vendor has not already done this with a factory bootloader and that factory loader being desirable for field use, it may use an I/O pin to determine which one boots, have to look at the docs. If you choose to do this yourself it is not unwise to have a gpio pin pick two boot paths, you can then have a very small, ideally bug free dozen or so lines of assembly that read the gpio pin and branch to a fixed point in flash that you choose Say 0x00500000 and 0x00600000 for example depending on how big you think your applications really will be. Then you can do a copy and jump into ram if the user desires loading the flash and then you can choose to load one or the other. The handful of lines of code could be a few dozen and do a checksum of some sort of the selected bank and the not selected if the selected is bad and did not complete. or a third bootloader that you provide in case the two do not checksum.
Tons of solutions, generally if you do not have separately banked flashes you need to branch to ram and have more freedom as to how to design your memory space (assuming the flash can be erased in pages). Otherwise you might want to just go with the banking solution from the chip vendor.
So all of this is documented in documents from arm and Atmel (microchip) that you should have had before starting work on this device. The only thing remotely related to arm in any of this is how the vector table works. All of the rest, the addresses, sizes, etc are all chip vendor implementation. So most of your reading is in the chip vendors docs, in this case they have the huge datasheet approach (rather than separate data sheet and reference manual approach).
You need to re-read what I found about sam-ba if you want to use that if it works for you, the nature of the flash implementation, is it in application programmable, etc. And then you design not only the functionality of your bootloader but the address space, whether it executes in flash or ram.
Edit
In case I did not understand the question.
The arm reset vector is at 0x00000004 not 0x00000000 (for the cortex-ms) and it is the address of the handler ORRED with one. Address 0x00000000 is the stack pointer initialization value, if you choose to init the stack pointer in code and not using this mechanism you can put whatever you want there.
If you want to change the reset handler address then you have to modify 0x00000004 which on some parts you can change without an erase (often flashes either work by erasing to all ones then you can write zeros, can't write ones but can changes ones to zeros on a per byte/word/chunk basis). So to change this you likely need to save it erase the block/page, change the bits you want and write back. You might for example be able to change it from 0x004001d9 to sah 0x004101d9 or to 0x004000d9, but not worth trying to do that. The value is the address of the handler ORRED with one.
It is not a branch as code is not executing at this point (normally/assumed) it is the logic reading that location and using that as the starting point, the first fetch not branch.
And as pointed out look at where the vector table is in the project and then modify that to point at your alternate reset handler. It might be code that looks like this
.word STACK_END
.word reset_handler
.word
in this case some fill/dummy vector for many of the rest. Just replace the reset_handler or whatever you find with your handler, remember this is a bootloader and you need to bootstrap C if you plan to call any C functions, worse if C++ or other language.

Related

C program in Docker: fwrite(3) and write(2) fail to modify files on Windows but not on MacOS

I am writing a guest OS on top of Linux (Ubuntu distribution) within a Docker container. The filesystem is implemented as a single file resting inside the host OS, so anytime a file is changed in the guest OS filesystem, the file on the host OS must be opened, the correct block(s) must be overwritten, and the file must be closed.
My partner and I have developed the following recursive helper function to take in a block number and offset to abstract away all details at the block-level for higher level functions:
/**
* Recursive procedure to write n bytes from buf to the
* block specified by block_num. Also updates FAT to
* reflect changes.
*
* #param block_num identifier for block to begin writing
* #param buf buffer to write from
* #param n number of bytes to write
* #param offset number of bytes to start writing from as
* measured from start of file
*
* #returns number of bytes written
*/
int write_bytes(int block_num, const char *buf, int n, int offset) {
BlockTuple red_tup = reduce_block_offset(block_num, offset);
block_num = red_tup.block;
offset = red_tup.offset;
FILE *fp = fopen(fat->fname, "r+");
int bytes_to_write = min(n, fat->block_size - offset);
int write_n = max(bytes_to_write, 0);
fseek(fp, get_block_start(block_num) + offset, SEEK_SET);
fwrite(buf, 1, write_n, fp); // This line is returning 48 bytes written
fclose(fp);
// Check if there are bits remaining
int bytes_left = n - write_n;
if (bytes_left > 0) {
// Recursively write on next block
int next_block = get_free_block();
set_fat_entry(block_num, next_block); // point block to next block
set_fat_entry(next_block, 0xFFFF);
return write_bytes(next_block, buf + write_n, bytes_left, max(0, offset - fat->block_size)) + write_n;
} else {
set_fat_entry(block_num, 0xFFFF); // mark file as terminated
return write_n;
}
}
The issue is that fwrite(3) is reporting 48 bytes written (when n is passed as 48) but hexdumping the file on the host OS reveals no bytes have been changed:
00000000 00 01 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00008000
This is particularly wacky because when my partner runs the code on the exact same commit (with no uncommitted changes), her write goes through and the file on the host OS hexdumps to:
00000000 00 01 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000100 66 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |f1..............|
00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000120 00 01 00 00 02 00 01 06 e7 36 75 63 00 00 00 00 |.........6uc....|
00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000200 e0 53 f8 88 c0 0d 37 ca 84 1f 19 b0 6c a8 68 7b |.S....7.....l.h{|
00000210 57 83 cf 13 f0 42 21 d3 21 e1 da de d4 8a f1 e6 |W....B!.!.......|
00000220 f0 12 98 fb 1c 30 4c 04 b3 16 1d 96 17 ba d7 5a |.....0L........Z|
00000230 7e f3 8a f5 6a 42 6b ef 58 f6 bc 01 db 0c 02 53 |~...jBk.X......S|
00000240 e5 10 7e f3 4a d5 3f ac 8e 38 82 c3 95 f8 11 8e |..~.J.?..8......|
00000250 a6 82 eb 3b 24 56 9a 75 44 36 8b 25 60 83 4c 04 |...;$V.uD6.%`.L.|
00000260 07 9e 14 99 9c 9f 87 3c 8a d4 c3 e8 17 60 81 0e |.......<.....`..|
00000270 bc eb 1d 35 68 fc d5 be 4f 1c 9d 5e 72 57 65 01 |...5h...O..^rWe.|
00000280 b7 43 54 26 d6 6d ba 51 bf 12 8c a1 03 d5 66 b3 |.CT&.m.Q......f.|
00000290 90 0d 60 b8 95 8d 15 bd 53 9a 70 77 4f 7a 04 1e |..`.....S.pwOz..|
000002a0 9e b2 4c 9a 79 dd de 48 cd fe 1e dc 57 7d d1 7f |..L.y..H....W}..|
000002b0 3f f5 77 96 fa e7 d7 33 33 48 ce 0a 4d 61 ab 96 |?.w....33H..Ma..|
000002c0 5f c4 88 bf c6 3a 09 37 76 c4 b8 db bc 6a 7d c0 |_....:.7v....j}.|
000002d0 c4 89 68 e7 b4 70 f8 a6 a8 00 9d c4 63 da fb 66 |..h..p......c..f|
000002e0 be d2 cd 68 1c d2 ff bf 00 e9 37 ab 6b 1a 3c f2 |...h......7.k.<.|
000002f0 7b c1 a2 c4 46 ae db 93 b4 4f 64 79 14 2a 1a d4 |{...F....Ody.*..|
00000300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00008000
The 48 bytes I'm referring to that don't get written are the bytes written to the directory block running from address 00000100-0000012E (the bytes below that represent the actual file being written, the code seg faults on my end before reaching that write). It's worth noting my container can still format the filesystem file, so all writes aren't broken. This snippet just represents the first write that did not work.
We are both running the code in an identical Docker container. The only difference I could imagine is my computer is a Windows and hers is a Mac. What could possibly be the issue?
The very first thing I believed was that there was some conflict with the host OS that blocked my write, but assigning and printing the return value of fwrite(3) returned that 48 bytes were indeed written on both machines.
I was also expecting that my buffer was simply all 0s (it is initially allocated using calloc(3)), but printing out the first 48 bytes of the buffer proved that theory false.
I finally considered that this was some issue with the higher level interface in <stdio.h> instead of the lower level one in <unistd.h>. I replaced fopen(3), fwrite(3), flseek(3), fclose(3) each with their lower-level equivalents (write(2) etc) and it still turned up 48 bytes written with no actual change to the files.
EDIT:
The guest OS filesystem can be formatted with respect to user parameters. All testing above was performed with a block size of 256 bytes and 128 blocks total. I've attempted the exact same write sequence again with a block size of 1024 bytes and 16384 blocks total, and there was no error. It's still unclear why the code works on my partner's machine for both format configs and not mine, but this may narrow it down.
Running strace reveals the following excerpt around the write:
openat(AT_FDCWD, "minfs", O_RDWR) = 4
newfstatat(4, "", {st_mode=S_IFREG|0777, st_size=32768, ...}, AT_EMPTY_PATH) = 0
lseek(4, 0, SEEK_SET) = 0
read(4, "\0\1\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 256) = 256
write(4, "f1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 48) = 48
close(4)
It again appears the bytes get written, but a hd after the program finishes reveals the same output as above. My thought was perhaps the bytes written in the excerpt are overwritten later on, but the only write after the excerpt above in the strace is:
lseek(4, 0, SEEK_SET) = 0
read(4, "\0\1\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 320) = 320
write(4, "\0", 1) = 1
close(4)
which should be at address 320, squarely after the write at address 256 above.
It turns out the mismatch was due to undefined behavior concerning when changes were synchronized in mmap(2). There was a section of code where a region of memory mapped via mmap(2) was changed and then immediately followed by reads/writes to the file on the host OS containing the mapped region of memory. It seems the Mac would write through the changes before the following section while the Windows wouldn't synchronize until after the fact, resulting in the undefined behavior.
The problem was fixed by making a call to msync(2) immediately after modifying the mapped region from mmap(2) with the MS_SYNC flag forcing the write-through behavior.
Links to documentation here: mmap(2), msync(2).

What is the Informix database file extension

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.

Xbee sending wrong ZDO responses

I´m playing around with two Xbees, one defined as coordinator, another as router. I want to read information about the network interoperably so i decided to use the ZDO messages.
I send a message like this ((profile ID 0x00 00, cluster ID 0x 00 31) and receive for example the following response from the router:
7E 00 2D 91 00 13 A2 00 40 E5 F0 B4 FB CE 00 00 80 31 00 00 01 2C 00 01 00 01 58 CE C1 8D 7A 3F 2D 40 AB F0 E5 40 00 A2 13 00 00 00 04 02 00 FF 33
Correct answer cluster ID: 0x 80 31
Focussing on the RF Data i have the following:
2C 00 01 00 01 58 CE C1 8D 7A 3F 2D 40 AB F0 E5 40 00 A2 13 00 00 00 04 02 00 FF
I now try to decode this hex string and face some problems.
From my point of view, this string should be encoded like defined within the ZigBee Spec from 2012, at Table 2.126 and 2.127
Unfortunately this don´t work for me. If i ignore, that the first byte should be the status and take the first two of them, i can read out NeighborTableEntries, StartIndex, NeighborTabelListCount. But when it comes to the NeighTableList i only can read out the Extended PAN id, the extended address and the network address, the rest of the string does not fit to the standard. Am i doing something wrong here or does the xbee´s don´t stick to the standard?
2C = Sequence Number
00 = Status (Success)
01 = 1 entry (total)
00 = starting at index 0
01 = 1 entry (in packet)
58 CE C1 8D 7A 3F 2D 40 = Extended Pan ID
AB F0 E5 40 00 A2 13 00 = IEEE address
00 00 = NodeId
04 = (Coordinator, RxOnWhenIdle)
02 = (Unknown Permit Join)
00 = (Coordinator)
FF = (LQI)
The values after the NodeId are bitmasks, not bytes.

How does raw result format returned from Microsoft SQL Server looks like?

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.

Can anyone guess what protocol these packets belong to?

We see these packets being injected in an FTP-DTP channel during a downlink file transfer on Telstra's NEXTG mobile network. We are not sure if these are network level packets, a problem with our 3G modem (HC25 based) or something like our firewall injecting in the stream.
Using a tool we noticed that the PPP framing fails with protocol length errors, so they are mostly likely mobile network packets.
I am hoping someone here can identify the signature of the packets so that I can chase this up with the appropriate vendor.
There is definitely a format to these packets: -
Packet1:
00 00 00 24 c4 b8 7b 1a 00 90 7f 43 0f a1 08 00 45 00 01 10 f4 4e 00 00 40 06 2f 13 cb 7a 9d e9 7b d0 71 52 7a ed 04 06 8c 61 5d a9 01 f7 0c eb 50 10 ff ff 58 b9 00 00
Packet2:
00 00 00 24 c4 b8 7b 1a 00 90 7f 43 0f a1 08 00 45 00 00 ff 6b 50 00 00 40 06 b8 22 cb 7a 9d e9 7b d0 71 52 7a ed 04 06 8c 61 7b 82 01 f7 0c eb 50 10 ff ff a3 79 00 00
Packet3:
00 00 00 24 c4 b8 7b 1a 00 90 7f 43 0f a1 08 00 45 00 02 20 5b 50 00 00 40 06 c7 01 cb 7a 9d e9 7b d0 71 52 7a ed 04 06 8c 61 7c 59 01 f7 0c eb 50 10 ff ff e2 5d 00 00
Packet4:
00 00 00 24 c4 b8 7b 1a 00 90 7f 43 0f a1 08 00 45 00 01 38 d8 52 00 00 40 06 4a e7 cb 7a 9d e9 7b d0 71 52 7a ed 04 06 8c 62 42 f9 01 f7 0c eb 50 10 ff ff 20 91 00 00
Packet5:
00 00 00 24 c4 b8 7b 1a 00 90 7f 43 0f a1 08 00 45 00 00 d0 4d 58 00 00 40 06 d6 49 cb 7a 9d e9 7b d0 71 52 7a ee 04 08 4b fb 0b 8f 03 5d 51 1a 50 10 ff ff e9 88 00 00
I converted your packet trace snippet into a format understood by text2pcap so I could convert them into the pcap format for viewing in Wireshark (a very handy packet capture and analysis tool):
Looks like some sort of IPv4 multicast traffic at a very rough guess. Here's what I got from the first packet (rest came up as malformed):
No. Time Source Destination Protocol Info
1 0.000000 7b:1a:00:90:7f:43 00:00:00_24:c4:b8 0x0fa1 Ethernet II
Frame 1 (31 bytes on wire, 31 bytes captured)
Arrival Time: Dec 1, 2009 00:33:05.000000000
[Time delta from previous captured frame: 0.000000000 seconds]
[Time delta from previous displayed frame: 0.000000000 seconds]
[Time since reference or first frame: 0.000000000 seconds]
Frame Number: 1
Frame Length: 31 bytes
Capture Length: 31 bytes
[Frame is marked: False]
[Protocols in frame: eth:data]
Ethernet II, Src: 7b:1a:00:90:7f:43 (7b:1a:00:90:7f:43), Dst: 00:00:00_24:c4:b8 (00:00:00:24:c4:b8)
Destination: 00:00:00_24:c4:b8 (00:00:00:24:c4:b8)
Address: 00:00:00_24:c4:b8 (00:00:00:24:c4:b8)
.... ...0 .... .... .... .... = IG bit: Individual address (unicast)
.... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
Source: 7b:1a:00:90:7f:43 (7b:1a:00:90:7f:43)
Address: 7b:1a:00:90:7f:43 (7b:1a:00:90:7f:43)
.... ...1 .... .... .... .... = IG bit: Group address (multicast/broadcast)
.... ..1. .... .... .... .... = LG bit: Locally administered address (this is NOT the factory default)
Type: Unknown (0x0fa1)
Data (17 bytes)
0000 08 00 45 00 01 10 f4 4e 00 00 40 06 2f 13 cb 7a ..E....N..#./..z
0010 9d .
Data: 080045000110F44E000040062F13CB7A9D
These look like ordinary TCP packets but with two extra 00 bytes tagged on at the front. Not sure why that would happen, but they appear to be from 00-90-7f-43-0f-a1 (Watchguard) to 00-24-c4-b8-7b-1a (Cisco).
IP header is 45 00 01 10 f4 4e 00 00 40 06 2f 13 cb 7a 9d e9 7b d0 71 52
TCP header is 7a ed 04 06 8c 61 5d a9 01 f7 0c eb 50 10 ff ff 58 b9 00 00
So you can get the rest of the details from there.
00:24:c4 is a NIC from Cisco and 00:90:7F is a NIC from WatchGuard.
From the IEEE OUI Registry.
How much help that might be ... don't know. Might therefore be an attempted VPN connection.
As already decoded by others:
first 6+6+2 bytes identifying NIC and Ethernet II.
bytes 0x0800 EtherType telling that it is IP. http://en.wikipedia.org/wiki/EtherType
next octet starting with nibble "4" is IPv4
etc.

Resources