How do I find what kernel structure something points to? - linux

I'm trying to debug an issue with kernel, where some function overwrites a random part of memory. I got some kernel oops on trying to read some unavailable memory area (usually 0x0...00282), which wasn't very helpful in debugging. But now I run into something potentially helpful - corruption happened in the file cache, so ended up with a nice fragment like this:
000bfc0: f0ef cf17 1888 ffff 8202 0000 0000 0000 ................
000bfd0: a0af 11a4 0a88 ffff a0af 11a4 0a88 ffff ................
000bfe0: a0af 11a4 0a88 ffff 0094 aab3 0b88 ffff ................
000bff0: 8202 0000 0000 0000 214e 1281 ffff ffff ........!N......
So I've got my typical signature included two times (0x0282... in reverse order) and some data that looks like it could contain valid pointers. Is there any good way to try to identify the types of structures it points at? Or maybe structure (allocation) sizes at least? Are there any other useful information I could pull out of this?
I'm hoping that this fragment could help me figure out which module/function writes to the random address.

Related

What's machine readable code's language? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Basically, what I'm asking is what's the language that the computer understands...
I have seen this post explaining a little https://www.quora.com/How-are-exe-files-created-And-what-programming-language-are-used-in-creating-them but it only refers to it as "machine readable code".
I wanna know what all the programming languages are converted to when compiled.
Is it possible to code knowing that "machine language" without using a compiler?
It's says it converts to "operating system" or "execution engine (virtual machine)" but is that it, can I take the notepad and just writte there that, save it as .exe and it will do what it says?
If you can't create a .exe without .exe then how do you do it?
Like, can I create a stand-alone windows application without any program like Visual Studio/Visual Basic?
The computer executes machine-code. That depends on its CPU. That's the reason you need to compile software for a special CPU-class (e.g. i386, SPARC, ...). Because they understand different machine-codes or they are built up very differently (e.g. RISC vs. CISC).
Between the highest level of program-code and the lowest level of machine-code there can be multiple layers between (e.g. assembler, object-code, ...). Layering (hiding of complexity in the layer below) is one of the most important concepts in technology.
And basically we differ between compiler and interpreter. The compiler translates a high-level code (from the human) to a low-level (e.g. machine-code). The interpreter is a running program that takes its input as commands. So it reads the code and acts as requested.
Normally interpreters are slower but more independent regarding the platform (if you have the the interpreter-program on multiple platforms).
The compiled program is much quicker but needs to be special for every CPU.
EXE is a format of machine-code. There are several different regarding the operating system.
I already mentioned assembler. It is a bit above machine-code and therefore readable for humans. In disassembling you take a program (a machine-code binary) and translate is into assembler.
Machine-code and assembler is a pretty straight mapping. So 1 line in assembler will produce - lets say - 1 to 5 lines in machine code.
1 line in a high-level language (e.g. C++) will produce much more lines in machine-code.
So in disassembling you try to understand the program and can use that information for further needs (e.g. how is a unlock-code expected, cracking, ...).
First off that linked reference is a bad thing for stack overflow, it could go away and ruin this whole question making it something we have to discard.
Second that reference is clearly about JAVA and JVM and extremely misleading right off the bat, if you dont know this stuff, that is a very bad article to start with.
As a programmer I assume you understand that if you give 100 programmers a programming task you are going to end up with somewhere between 1 and 100 different solutions.
hardware is no different, give 100 chip designers the same design task, you get between 1 and 100 different designs. hardware/board designers, same deal. If you tell the chip designers to invent their own instruction set and design a processor it is going to lean toward 100 different designs. if you give them the instruction set (machine code specification) you will still get between 1 and 100 different designs.
If it is CISC or CISC like you may end up with microcoding, with RISC you could too but that is kind of the idea of RISC to not need/want microcoding.
All programming languages is way too vague. At the same time they are generally converted to some lower level language, and ultimately to something parse-able. We have to be vague with an answer as there are exceptions to every statement I can make about this. But C/C++ are "compiled", generally, into assembly langauge for a particular target, the one the compiler is either told to target and often the one you are running it on, a "cross-compiler" is used to compile for a different target. I dont want to keep using the generally, and mostly and other vague terms...then the assembler converts the assembly language into mostly machine code, but if it is an object then some things are left for the linker to fill in and finalize. but even the .exe or other similar foramats (coff, elf, etc) the majority of the file is the program, machine code and data, but some of the file tells the operating system how to load that program and start it. You have to look up each "binary" file format type to see how they do this. And then in some cases it may still also be operating system dependent.
There is absolutely no reason that you cant generate these executable files directly or in any path you choose. you can use a hex editor (notepad NOT being one of these) and start typing in the bytes for the file, the .exe headers, the machine code, the data, the whole thing. you can certainly write a program in some language compile that and run it and that program can directly create another program, not using a compiler just write bytes out.
JAVA, early Pascal, Python, BASIC for that matter. These dont necessarily (although Pascal does these days) compile directly into "machine code" for the processor you are running on. By design. JAVA and Python desire to run everywhere, operating system independent. They have their own machine code, their compilers compile the source down into a machine code that is not the machine code for the target processor, the one you are running on, but a generic one they invented. Then you have a JVM JAVA Virtual Machine, which is a program, probably not written in JAVA, that IS operating system dependent and reads the bytes of that java machine code and executes it as a processor would. same for python and in the early days the same for pascal. BASIC, traditionally you read the BASIC code at runtime and parse and run it as you go. granted all of these likely have a toolchain someone wrote (or just gcc for some of them) that can instead of compiling to the langauge specific target, instead can be compiled into machine code for the processor you are running on, typically and by design not but, sometimes can be done.
processors themselves are not that much different, just logic that reads the machine code, parses the bits out and does what the bits say to do. just like the JVM does for JAVA, but in hardware and much faster. Sometimes, more likely with CISC (x86), you have microcode, yet another instruction set, exactly like the JVM in the sense that it perhaps with the help of hardware/logic takes the machine code, and in microcoded software breaks that up and executes it. we generally dont get to see that microcode because you take 100 designers and you get 100 results, each generation of processor they dont want to carry around the same microcode, x86 being a perfect example of this, esp since intel has two or more design centers that do their own thing and every other or every third chip design is from one of those design centers, so we keep going between the preferences of those design centers. or at least they used to do that dont know what they do now.
yes you can absolutely write a windows program without visual studio/visual basic. you can use a hex editor and just type in the bytes, you can write in assembly language and assemble it with an assembler (and linker depending) that is not visual anything based (take gnu binutils for example).
as mentioned in other answers and comments, or not. before there were any of these tools "compiling" and "assembling" was a human that wrote down what they wanted to do (probably in a flow chart) then wrote it down again in some form of assembly language, something human readable, then next to that or starting on a new page, wrote the machine code. and then flipped switches or otherwise entered that machine code into the processor and started it. using that method you can eventually write an assembler, and then now that you have an assembler you can write that assembler again in assembler and not hand written machine code. and now that you have an assembler you can invent languages and implement those in assembler, then you can re-write those in the same language and compile them with that langauge. and use that language to make other languages. And cross compile langauges or assemble, for other platforms which you have invented but have no tools and dont want to hand write machine code. repeat this for decades and here we are. even the logic is designed using programming languages verlog and/or vhdl, which clearly are influenced by languages like C and ADA, which came before them.
I take this function, but what is the difference between a function and a program? let you ponder that.
unsigned int fun ( unsigned int a, unsigned int b )
{
return (a+b);
}
I compile it. the compiler produces assembly language as its output
.arch armv5t
.fpu softvfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 2
.eabi_attribute 34, 0
.eabi_attribute 18, 4
.arm
.syntax divided
.file "so.c"
.text
.align 2
.global fun
.type fun, %function
fun:
# args = 0, pretend = 0, frame = 0
# frame_needed = 0, uses_anonymous_args = 0
# link register save eliminated.
add r0, r0, r1
bx lr
.size fun, .-fun
.ident "GCC: (Ubuntu 5.2.1-22ubuntu1) 5.2.1 20151010"
.section .note.GNU-stack,"",%progbits
then I assemble that into an object. a hexdump of that:
0000000 457f 464c 0101 0001 0000 0000 0000 0000
0000010 0001 0028 0001 0000 0000 0000 0000 0000
0000020 019c 0000 0000 0500 0034 0000 0000 0028
0000030 000a 0007 0001 e080 ff1e e12f 4700 4343
0000040 203a 5528 7562 746e 2075 2e35 2e32 2d31
0000050 3232 6275 6e75 7574 2931 3520 322e 312e
0000060 3220 3130 3135 3130 0030 2941 0000 6100
0000070 6165 6962 0100 001f 0000 3505 0054 0306
0000080 0108 0109 0412 0114 0115 0317 0118 0119
0000090 021a 021e 2e00 7973 746d 6261 2e00 7473
00000a0 7472 6261 2e00 6873 7473 7472 6261 2e00
00000b0 6574 7478 2e00 6164 6174 2e00 7362 0073
00000c0 632e 6d6f 656d 746e 2e00 6f6e 6574 472e
00000d0 554e 732d 6174 6b63 2e00 5241 2e4d 7461
00000e0 7274 6269 7475 7365 0000 0000 0000 0000
00000f0 0000 0000 0000 0000 0000 0000 0001 0000
0000100 0000 0000 0000 0000 0004 fff1 0000 0000
0000110 0000 0000 0000 0000 0003 0001 0000 0000
0000120 0000 0000 0000 0000 0003 0002 0000 0000
0000130 0000 0000 0000 0000 0003 0003 0006 0000
0000140 0000 0000 0000 0000 0000 0001 0000 0000
0000150 0000 0000 0000 0000 0003 0005 0000 0000
0000160 0000 0000 0000 0000 0003 0004 0000 0000
0000170 0000 0000 0000 0000 0003 0006 0009 0000
0000180 0000 0000 0008 0000 0012 0001 7300 2e6f
0000190 0063 6124 6600 6e75 0000 0000 0000 0000
00001a0 0000 0000 0000 0000 0000 0000 0000 0000
*
00001c0 0000 0000 001b 0000 0001 0000 0006 0000
00001d0 0000 0000 0034 0000 0008 0000 0000 0000
00001e0 0000 0000 0004 0000 0000 0000 0021 0000
00001f0 0001 0000 0003 0000 0000 0000 003c 0000
0000200 0000 0000 0000 0000 0000 0000 0001 0000
0000210 0000 0000 0027 0000 0008 0000 0003 0000
0000220 0000 0000 003c 0000 0000 0000 0000 0000
0000230 0000 0000 0001 0000 0000 0000 002c 0000
0000240 0001 0000 0030 0000 0000 0000 003c 0000
0000250 002e 0000 0000 0000 0000 0000 0001 0000
0000260 0001 0000 0035 0000 0001 0000 0000 0000
0000270 0000 0000 006a 0000 0000 0000 0000 0000
0000280 0000 0000 0001 0000 0000 0000 0045 0000
0000290 0003 7000 0000 0000 0000 0000 006a 0000
00002a0 002a 0000 0000 0000 0000 0000 0001 0000
00002b0 0000 0000 0011 0000 0003 0000 0000 0000
00002c0 0000 0000 0094 0000 0055 0000 0000 0000
00002d0 0000 0000 0001 0000 0000 0000 0001 0000
00002e0 0002 0000 0000 0000 0000 0000 00ec 0000
00002f0 00a0 0000 0009 0000 0009 0000 0004 0000
0000300 0010 0000 0009 0000 0003 0000 0000 0000
0000310 0000 0000 018c 0000 000d 0000 0000 0000
0000320 0000 0000 0001 0000 0000 0000
000032c
not necessarily for this program but often easier to see what the compiler produced by disassembling the object rather than the verbose assembly.
Disassembly of section .text:
00000000 <fun>:
0: e0800001 add r0, r0, r1
4: e12fff1e bx lr
That happens to have the machine code for us, so we could just type those bytes in. As written this isnt a complete program as it needs an operating system specific entry and exit at a minimum.
I could run this code on this processor I have chosen bare metal, and could for example wrap it with this bootstrap:
.globl _start
_start:
mov sp,#0x8000
bl fun
b .
assemble and link and I get this for example
Disassembly of section .text:
00000000 <_start>:
0: e3a0d902 mov sp, #32768 ; 0x8000
4: eb000000 bl c <fun>
8: eafffffe b 8 <_start+0x8>
0000000c <fun>:
c: e0800001 add r0, r0, r1
10: e12fff1e bx lr
I can convert that into a binary image that could be loaded into ram or flash depending for that processor and run
0000000 d902 e3a0 0000 eb00 fffe eaff 0001 e080
0000010 ff1e e12f
0000014
Not using basic, not using visual studio, not running windows, I can write this program
#include <stdio.h>
static const unsigned int fun[]=
{
0xe3a0d902,
0xeb000000,
0xeafffffe,
0xe0800001,
0xe12fff1e,
};
int main ( void )
{
FILE *fp;
fp=fopen("fun.bin","wb");
if(fp==NULL) return(1);
fwrite(fun,1,sizeof(fun),fp);
fclose(fp);
return(0);
}
compile and run it (yes an exe from an exe) and it produces the same binary file shown in a hexdump here:
0000000 d902 e3a0 0000 eb00 fffe eaff 0001 e080
0000010 ff1e e12f
0000014
I could also just take a hex editor and just type those bytes in. and not use a language to create this binary file. although it is still an exe from an exe because I used a hexeditor which is a program. and I say exe here loosly as this is not in the .exe file format, but exe in the sense that it is an executable program although mostly useless.
yes I am well aware that I didnt load r0 nor r1 before calling fun, doesnt matter processor registers wake up with bits in them (except in some silicon simulations which are not two state but three, four, or more state and depending on the logic design) so the add will work.
Can I create a stand-alone windows application without any program like
Visual Studio/Visual Basic?
It's theorically possible, if you have time to spend (like hundred of years) if you really want to use a hexa-code is more than tedious, even with assembler, which is almost the lowest level before machine-code that is, let's say, human friendly...
To resume : You don't use a knife and bamboos to build the Titanic !

What will be the physical address of 000H and 29H ?

What will be the physical address of 0000H assume this segment address and offset address is 29H ?
I am reading the Assembly Language Step by Step 3rd Edition, the answer of this question inside the book which i mentioned is 2DH Bytes But How ?
I took basic steps to to solve my self and here it is my result:
0000 0000 0000 0010 1001 // segment address + offset addr (In Binary)
After calculation the result will be 41 in decimal and if we convert this to Hex it will be again 29H. Basically, the answer inside the book is 2DH, How ?
and there is another problem with 0001H which is segment address and the offset address is 19H. The answer inside the book is 1DH, How ?
Thanks :)

Why Linux/gnu linker chose address 0x400000?

I'm experimenting with ELF executables and the gnu toolchain on Linux x86_64:
I've linked and stripped (by hand) a "Hello World" test.s:
.global _start
.text
_start:
mov $1, %rax
...
into a 267 byte ELF64 executable...
0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
0000010: 0200 3e00 0100 0000 d400 4000 0000 0000 ..>.......#.....
0000020: 4000 0000 0000 0000 0000 0000 0000 0000 #...............
0000030: 0000 0000 4000 3800 0100 4000 0000 0000 ....#.8...#.....
0000040: 0100 0000 0500 0000 0000 0000 0000 0000 ................
0000050: 0000 4000 0000 0000 0000 4000 0000 0000 ..#.......#.....
0000060: 0b01 0000 0000 0000 0b01 0000 0000 0000 ................
0000070: 0000 2000 0000 0000 0000 0000 0000 0000 .. .............
0000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000b0: 0400 0000 1400 0000 0300 0000 474e 5500 ............GNU.
00000c0: c3b0 cbbd 0abf a73c 26ef e960 fc64 4026 .......<&..`.d#&
00000d0: e242 8bc7 48c7 c001 0000 0048 c7c7 0100 .B..H......H....
00000e0: 0000 48c7 c6fe 0040 0048 c7c2 0d00 0000 ..H....#.H......
00000f0: 0f05 48c7 c03c 0000 0048 31ff 0f05 4865 ..H..<...H1...He
0000100: 6c6c 6f2c 2057 6f72 6c64 0a llo, World.
It has one program header (LOAD) and no sections:
There are 1 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000010b 0x000000000000010b R E 200000
This seems to load the entire file (file offset 0 thru 0x10b - elf header and all) at address 0x400000.
The entry point is:
Entry point address: 0x4000d4
Which corresponds to 0xd4 offset in the file, and as we can see that address is the start of the machine code (mov $1, %rax1)
My question is why (how) did the gnu linker choose address 0x400000 to map the file to?
The start address is usually set by a linker script.
For example, on GNU/Linux, looking at /usr/lib/ldscripts/elf_x86_64.x we see:
...
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); \
. = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
The value 0x400000 is the default value for the SEGMENT_START() function on this platform.
You can find out more about linker scripts by browsing the linker manual:
% info ld Scripts
ld's default linker script has that 0x400000 value baked in for non-PIE executables.
PIEs (Position Independent Executables) don't have default base address; they're always relocated by the kernel, with the kernel's default being 0x0000555... plus some ASLR offset unless ASLR is disabled for this process or system-wide. ld has no control over this. Note that most modern systems configure GCC to use -fPIE -pie by default, so it passes -pie to ld, and turns C into asm that's position-independent. Hand-written asm has to follow the same rules if you link it that way.
But what makes 0x400000 (4 MiB) a good default?
It has to be above mmap_min_addr = 65536 = 64K by default.
And being plenty far away from 0 gives plenty more room to guard against NULL deref with an offset reading .text or .data/.bss memory (array[i] where array is NULL). Even without increasing mmap_min_addr (which this leave room for without breaking executables), usually mmap randomly picks high addresses so in practice we have at least 4MiB of guard against NULL deref.
2M-aligned is good
This puts it at the start of a page-directory in the next level up of the page tables means the same number of 4K page-table-entries will be split across fewer 2M page directory entries, saving kernel page-table memory and helping page-walk hardware cache better. For big static arrays, close to the start of a 1G subtree of the next level up is also good.
IDK why 4MiB instead of 2MiB, or what the developers' reasoning was. 4MiB is the 32-bit largepage size without PAE (4-byte PTEs so 10 bits per level instead of 9), but a CPU has to be using x86-64 page tables to be in 64-bit mode.
A low start address allows nearly 2 GiB of static arrays
(Without using a larger code model, where at least large arrays have to be addressed in ways that are sometimes less efficient. See section 3.5.1 Architectural Constraints in the x86-64 System V ABI document for details on code models.)
The default code model for non-PIE executables ("small") lets programs assume that any static address is in the low 2GiB of virtual address space. So any absolute address in .text/.rodata, .data, .bss can be used as a 32-bit sign-extended immediate in the machine code where that's more efficient.
(This is not the case in a PIE or shared library: see 32-bit absolute addresses no longer allowed in x86-64 Linux? for the things you / the compiler can't do in x86-64 asm as a result, notably addss xmm0, [foo + rdi*4] instead requires a RIP-relative LEA to get the array start address into a register. x86-64's only RIP-relative addressing mode is [RIP+rel32], without any general-purpose registers.)
Starting the executable's sections/segments near the bottom of virtual address space leaves almost the whole 2GiB available for text+data+bss to be that big. (It might have been possible to have a higher default, and have large executables make ld choose a lower address to make them fit, but that would be a more complicated linker script.)
This includes zero-initialized arrays in the .bss which don't make the executable file huge, just the process image in memory. In practice, Fortran programmers tend to run into this more than C and C++, since static arrays are popular there. For example gfortran for dummies: What does mcmodel=medium do exactly? has a good explanation of a build error with the default small model, and the resulting x86-64 asm difference for medium (where objects above a certain size threshold are not assumed to be in the low 2G or within +-2G of the code. But code and smaller static data still is so the speed penalty is minor.)
For example static float arr[1UL<<28]; is a 1 GiB array. If you had 3 of them, they couldn't all start inside the low 2 GiB (which may be all you need for hand-written asm), let alone have each element accessible.
gcc -fno-pie expects to be able to compile float *p = &arr[size-1]; to mov $arr+1073741820, %edi, a 5-byte mov $imm32. RIP-relative won't work either if the target address is more than 2GiB away from the code generating the address (or loading from it with movss arr+1073741820(%rip), %xmm0; RIP-relative is the normal way to load/store static data even in a non-PIE, when there's no runtime-variable index.) That's why the small-PIC model also has a 2GiB size limit on text+data+bss (plus gaps between segments): all static data and code needs to be within 2GiB of any other that might want to reach it.
If your code only ever accesses high elements or their addresses via runtime-variable indices, you only need the start of each array, the symbol itself, to be in the low 2 GiB. I forget if the linker enforces having the end-of-bss within the low 2GiB; it might since the linker script puts a symbol there that some CRT startup code might reference.
Footnote 1: There aren't any useful smaller sizes for a code model smaller than 2GiB. x86-64 machine code uses either 8 or 32-bit for immediates and addressing mode. 8-bit (256 bytes) is too small to be usable, and many important instructions like call rel32, mov r32, imm32, and [rip+rel32] addressing, are only available with 4-byte not 1-byte constants anyway.
Limiting to the low 2 GiB (instead of 4) means that addresses can safely be zero-extended as with mov edi, OFFSET arr, or sign-extended, as with mov eax, [arr + rdi*4]. Remember that addresses aren't the only use-case for [reg + disp32] addressing modes; [rbp - 256] can often make sense, so it's good that x86-64 machine code sign-extends disp8 and disp32 to 64-bit, not zero-extends.
Implicit zero-extension to 64-bit happens when writing a 32-bit register, as with mov-immediate to put an address in a register, where 32-bit operand-size is a smaller machine-code instruction than 64-bit operand-size. See How to load address of function or label into register (which also covers RIP-relative LEA).
Related for 32-bit Windows
Raymond Chen wrote an article about why the same 0x400000 base address is the default for 32-bit Windows.
He mentions that DLLs get loaded at high addresses by default, and a low address is far from that. x86-64 SysV shared objects can get loaded anywhere there's a large enough gap of address space, with the kernel defaulting to near the top of user-space virtual address-space, i.e. the top of the canonical range. But ELF shared objects are required to be fully relocatable so would work fine anywhere.
The 4MiB choice for 32-bit Windows was also motivated by avoiding the low 64K (NULL deref), and by picking the start of a page-directory for legacy 32-bit page tables. (Where the "largepage" size is 4M, not 2M for x86-64 or PAE.) With a bunch of Win95 and Win3.1 legacy memory-map reasons why at least 1MiB or 4MiB was partially necessary, and stuff like working around CPU bugs.
Page zero of task's virtual address space is kept unmapped so that null-pointer references could be catched through page-fault exception leading to SIGSEGV. 4 MB fit with "big page" granularity (as opposed to "normal page" granularity 4 KB) - so on settings with 4 MB page granularity, 0x000000 to 0x3FFFFF address range is unmapped, making 0x400000 the first valid address in task's virtual address space.

rfid tags: same tag, different codes on different readers

Is anyone familiar with RFID codes here?
I have a EM4102 type tag here. My handheld reader says on it's display:
EM4102 tag, ID 04178649C1
The same tag, when read on a Gigatek/Promag PCR125 CF-card reader gives me the exact same code:
04178649C1
However, an ACG RF PC CF-card reader gives me the code
20E8619283
This reader is capable of reading different types of tags and also reports the correct type (EM4x02, length 5 bytes).
I have tried a few readers of the same model and they all give me the same code.
I guess that reader just reports the code in a different way. Perhaps I have to shift some bits around (wouldn't be the first time) or there are error correction bits still included in the code?
FYI, the reader is documented here. The section regarding this type of tags just states:
The EM4x02 label only provides a 5 bytes serial number. The label
starts to send its response immediately after entering an energizing
field. Each transponder has its own unique serial number, which cannot
be changed.
Any clue what the reader is doing?
I figured it out myself.
20E8619283 in binary is:
0010 0000 1110 1000 0110 0001 1001 0010 1000 0011
These are five bytes, two nibbles each. Mirroring the bit order of each byte (bit 0 becomes bit 7, bit 1 becomes 2 etc.) I get:
0000 0100 0001 0111 1000 0110 0100 1001 1100 0001
which in hexadecimal notation is 04178649C1, the correct code.
So apparently the reader is not interpreting/reporting the bits in the right order...

How to calculate my GPIO port address

I have a Jetway NF81-T56 motherboard which has a header providing 8 I/O lines labeled GPIO30-GPIO37. There is no GPIO driver in my CentOS6 install, and I am attemptiing to write a driver. A Fintek F71869 Super IO chip provides the GPIO and other I/O functions. I can access and modify the GPIO3 registers through the 0x2e/0x2f ports, but haven't been able to access the data port using the GPIO BASE_ADDR set in the F71869 GPIO registers. I have read those registers, and the GPIO BASE_ADDR is set to 0x0a00. The manual page for the chip states:
The index port is BASE_ADDR[15:2] + 5 and the data port is BASE_ADDR[15:2] + 6
I have set the data port to 0x0f (as displayed by connected LEDs) and tried reading ports 0x0a00-0x0a7f. All returned 0xff, and not 0x0f. Does anyone know how to interpret the "BASE_ADDR[15:2]" notation syntax? I have tried searching the Internet and tried contacting the manufacturer, to no avail.
This is hardware-style vector (bitfield) notation, basically you right shift two places.
0x0a00 becomes 0x0280 if I'm doing it right in my head.
To draw it out here are the bits [15:0]
0x0a00 = 0000 1010 0000 0000
now select bits [15:2]
0000 1010 0000 00
which we re-format as [13:0] of a new vector
00 0010 1000 0000 = 0x0280
So it looks like you should be accessing at 0x0285 and 0x0286. However, you need to be sure you've got the board configured correctly, and more important you need to be sure that nothing else is also located at those addresses.

Resources