Reputation: 45
I want to print 12byte from specific memory address in kernel.
Following is my hard coding.
void *Unique_Id = 0x5C000234;
for(int i=0;i<12;i++){
printk("%02x ", *(uniqueId+i));
}
This is correct? or there are any other suggestion?
Please give me advice.
Thank you.
Upvotes: 1
Views: 3205
Reputation: 17503
Converting integers to pointers without a cast will produce a compiler warning, so the initialization should be:
void *Unique_Id = (void *)0x5C000234;
The kernel uses virtual addresses to access memory locations. The number 0x5C000234
is most likely a physical address of some registers in hardware I/O memory space. These need to be remapped into the kernel's virtual address space before their contents can be accessed. For hardware I/O memory, that is done by ioremap()
or one of the ioremap_*()
variants. Pointers to remapped I/O memory should be tagged with __iomem
:
void __iomem *Unique_Id = ioremap(0x5C000234, 12);
(The second parameter is the length of the mapping in bytes.)
ioremap()
will return NULL
if it fails to map the memory, so that should be checked:
if (Unique_Id == NULL) {
/* Deal with the error */
When the mapping is no longer required, iounmap()
can be called to unmap it:
iounmap(Unique_Id);
The contents of remapped I/O memory should not be accessed directly. There are specific functions for accessing 8-bit, 16-bit, 32-bit, and (on 64-bit systems) 64-bit quantities. These are readb()
and writeb()
(8-bit), readw()
and writew()
(16-bit), readl()
and writel()
(32-bit), and readq()
and writeq()
(64-bit). So the for
loop to print 12 successive bytes could be written as:
for (int i = 0; i < 12; i++) {
printk("%02x ", readb(Unique_Id + i));
}
(Note that pointer arithmetic on a void *
is a GCC extension, but is blessed by the Linux kernel developers.)
There are also memcpy_fromio()
and memcpy_toio()
functions for copying between normal kernel memory and I/O memory, so the 12-byte ID could be copied into a 12-byte array using memcpy_fromio()
:
u8 id[12];
memcpy_fromio(id, Unique_Id, 12);
for (int i = 0; i < 12; i++) {
printk("%02x ", id[i]);
}
(u8
is an unsigned 8-bit integer type defined by #include <linux/types.h>
.)
The normal usage of printk()
is to precede the format string with a "log-level" macro such as KERN_INFO
(relying on C string literal concatenation to combine it with the format string), and to end the format string with a new-line character:
for (int i = 0; i < 12; i++) {
printk(KERN_INFO "%02x\n", id[i]);
}
That would split the ID over 12 lines in the kernel log. There is a special KERN_CONT
macro to indicate that the message is a continuation of a previous message, so the proper way to combine the printk()
calls would be something like:
printk(KERN_INFO "%02x ", id[0]);
for (int i = 1; i < 11; i++) {
printk(KERN_CONT "%02x ", id[i]);
}
printk(KERN_CONT, "%02x\n", id[11]);
(It may be preferable to use snprintf()
to construct a string in a temporary array of char
and use a single call to printk()
to print it all in one go.)
The kernel's print format string processing has special extensions where the p
specifier for printing pointer values can be suffixed by various characters to change its behaviour. For example, the 12-byte ID could be printed by:
u8 id[12];
memcpy_fromio(id, Unique_Id, 12);
printk(KERN_INFO "%12ph\n", id);
That works for hex strings of up to 64 bytes.
See How to get printk format specifiers right for details of printk
format specifiers.
The kernel has a print_hex_dump()
function for printing hex dumps. The 12-byte ID could be printed as follows:
u8 id[12];
memcpy_fromio(id, Unique_Id, 12);
print_hex_dump(KERN_INFO, "Unique_Id: ", DUMP_PREFIX_NONE, 12, 1, id, 12, false);
(The parameters of print_hex_dump()
are level
(e.g. KERN_INFO
), prefix_str
(string prefixed to each line of output), prefix_type
(one of DUMP_PREFIX_NONE
, DUMP_PREFIX_ADDRESS
or DUMP_PREFIX_OFFSET
), rowsize
(number of bytes printed per row of output), groupsize
(number of bytes to print in each space-separated group), buf
(pointer to data to dump), len
(length of data to dump), ascii
(include ASCII after the hex output if true).
Upvotes: 3
Reputation: 21
I think since you want to print bytes so just cast the uniqueID + i to a character/unsigned character pointer
printk("%02x ", *((char *)(uniqueId+i)));
Upvotes: 0