My board is S3C6410, When i read the source code of uboot. there is something troubles me.
#define CONFIG_BOOTCOMMAND "nand read 0xc0008000 0x100000 0x500000;bootm 0xc0008000"
what does it mean ? it read the data from address of nand: 0x100000 , size of: 0x500000. To 0xc0008000 (SD-RAM), is it ?..
But the start-address of SD-RAM is : 0x50000000, how does address of 0xc0008000 make sense ?...out of range ?
Thanks.
my sdram size: 256M... nand boot..
There is some configure about it.
#define MEMORY_BASE_ADDRESS 0x50000000
#define CONFIG_NR_DRAM_BANKS 1 /* we have 2 bank of DRAM */
#define PHYS_SDRAM_1 MEMORY_BASE_ADDRESS /* SDRAM Bank #1 */
//#define PHYS_SDRAM_1_SIZE 0x08000000 /* 64 MB */
#define PHYS_SDRAM_1_SIZE 0x10000000
#define CFG_FLASH_BASE 0x00000000
It looks like you are reading it right. Address of 0xc0008000 would be destination of the read from nand.
I'd suggest you stop board boot to get U-Boot command prompt. Then do printenv, that may show something in your target setup that overrides the source you have shown. Also try the command manually.
it means 0x100000 address and 0x500000 size of nand should be written at address 0xc0008000.
Related
I want to write a Linux kernel module to modify the source MAC address of a packet that will be sent from my computer.
I have tried Netfilter hook at NF_INET_POST_ROUTING, but it can only process the L3(IP) header.
I'm looking forward to the L2(MAC) hook funtion.
As its name suggests, NF_INET_POST_ROUTING is an INET layer hook. I think that you need NF_BR_POST_ROUTING which lives in netfilter_bridge.h (source):
/* Bridge Hooks */
/* After promisc drops, checksum checks. */
#define NF_BR_PRE_ROUTING 0
/* If the packet is destined for this box. */
#define NF_BR_LOCAL_IN 1
/* If the packet is destined for another interface. */
#define NF_BR_FORWARD 2
/* Packets coming from a local process. */
#define NF_BR_LOCAL_OUT 3
/* Packets about to hit the wire. */
#define NF_BR_POST_ROUTING 4
I am trying to read kernel image and calculate a checksum value of this image. Firstly, I used a smc instruction to trigger a exception, and in the exception handler, I tried to read the first bytes of the image. I don't really know what the address is, but from some documents, I know the kernel image is decompressed in address like 0x20008000, 0x30008000 or 0xC0008000(they call this ZRELADDR, i don't really know whether this is the right address...). So I tried to read the memory like this:
uint32_t test;
test = * (uint32_t *)0x30008000;
DMSG("test : %x\n",test);
But the system crashed with a data abort exception,
core data-abort at address 0x30008000
fsr 0x00000005 ttbr0 0x7df7006a ttbr1 0x7df7006a cidr 0x0
cpu #0 cpsr 0x200001b3
r0 0x00000090 r4 0x7df4bf51 r8 0x00000000 r12 0x00000000
r1 0x09010000 r5 0x806665e0 r9 0x00000000 sp 0x7df77f50
r2 0x0000000d r6 0x7f002000 r10 0x00000000 lr 0x7df273ff
r3 0x30008000 r7 0x7df77f60 r11 0x00000000 pc 0x7df052f0
ERR TEE-CORE:tee_pager_handle_fault:602: Unexpected page fault! Trap CPU
PANIC: tee_pager_handle_fault core/arch/arm/mm/tee_pager.c:603
I guess I am on the wrong way. Does anyone know how to read the kernel image in runtime environment?
Thanks for your help!
EDIT:Thanks for your reply. I am talking about secure kernel. I am trying to check the integrity of the kernel under TrustZone, and to insure the kernel haven't be compromised. So I guess a checksum like hash value may help me. Also, I am a novice who is trying to be familiar with the memory system of arm, so I tried to start with simple read some certain memory address. I have tried to read 0xc0000000 as Artless Noise said, but the same error occurs again. Again I tried to find "_test" and "stext" address in System.map, which is 0x80008000, and error occurs again.
The beginning of the RAM is usually mapped at 0xC0000000. This depends on CONFIG_PAGE_OFFSET:
- VMSPLIT_3G: 0xC0000000
- VMSPLIT_2G: 0x80000000
- VMSPLIT_1G: 0x40000000
Note that this is a virtual address if you have an MMU (usual case), the physical address will depend on your actual architecture (it may or may not be 0x00000000). The kernel is loaded a few pages after that, at an offset of 0x8000.
So, you can probably find the (uncompressed) kernel at 0xC0008000 but it may as well be located somewhere else.
You can also try to ioremap() offset 0x8000 of your RAM.
Can you give us a bit more information on the particular SoC you are working on?
If you are in secure mode and you believe that in secure mode it access physical address then from below these macro you can deduce the physical address.
The physical address at which kernel loads is PHYS_OFFSET + TEXT_OFFSET (text offset is 0x8000),
PHYS_OFFSET definition will be depend on the CONFIG_ARM_PATCH_PHYS_VIRT patch.
if CONFIG_ARM_PATCH_PHYS_VIRT is defined, then PHYS_OFFSET will be equal to __pv_phys_offset otherwise PHYS_OFFSET will be defined as CONFIG_PHYS_OFFSET in your kernel config file.
I am using Fedora 17 running on board with integrated graphics.
Given that I am able to manipulate content of physical memory, how can I find out the physical memory offsets that I could write to in order to display something on the screen?
I tried to lookup 0xB8000 and 0xB0000 offsets but they contain all 0xff.
Is there a specific pattern that starts video buffer in memory?
Is there any good source of information about this topic?
The root cause of my problem was that Linux is not using legacy video mode, so the memory at 0xB8000 is restricted (in my case read only). However issuing an interrupt can switch to other modes:
INT 10 - VIDEO - SET VIDEO MODE
AH = 00h
AL = desired video mode (see #00010)
Found on: http://www.delorie.com/djgpp/doc/rbinter/id/74/0.html
Living like it's 1989
#include <linux/fb.h>
#define DEV_MEM "/dev/fb0"
/* Screen parameters (probably via ioctl() and /sys. */
#define YRES 240
#define XRES 320
#define BYTES_PER_PIXEL (sizeof(unsigned short)) /* 16 bit pixels. */
#define MAP_SIZE XRES*YRES*BYTES_PER_PIXEL
unsigned short *map_lbase;
if((fd = open(DEV_MEM, O_RDWR | O_SYNC)) == -1) {
fprintf(stderr, "cannot open %s - are you root?\n", DEV_MEM);
exit(1);
}
// Map that page.
map_lbase = (unsigned short *)mmap(NULL, MAP_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if((long)map_lbase == -1) {
perror("cannot mmap");
exit(1);
}
Humons - Framebuffer API doc, Framebuffer Doc dir.
Smart Humons - Internals, Deferred I/O doc or how to emulate memory mapped video.
You can not use 0xB8000 and 0xB0000 directly as those are physical addresses. I assume you are in user space and not writing a kernel driver. Under Linux, we normally have the MMU enable; In other words, we have virtual memory. Not all processes/users have access to video memory. However, if you are allowed, you can mmap a framebuffer device to your address space. It is best to let the kernel give you an address and not request a specific one.
Or see how professionals do it.
Man: mmap
Edit: If you aren't root, you can still use Unix permissions on /dev/fb0 (or which ever device) to give group permission to read/write or use some sort of login process that gives a user on the current tty permission.
Maybe you could start around here:
http://www.tldp.org/HOWTO/Framebuffer-HOWTO/
But modern video graphics are in no way as simple as "finding where in the meory is the VRAM" and writing there.
On a ARM based system running Linux, I have a device that's memory mapped to a physical address. From a user space program where all addresses are virtual, how can I read content from this address?
busybox devmem
busybox devmem is a tiny CLI utility that mmaps /dev/mem.
You can get it in Ubuntu with: sudo apt-get install busybox
Usage: read 4 bytes from the physical address 0x12345678:
sudo busybox devmem 0x12345678
Write 0x9abcdef0 to that address:
sudo busybox devmem 0x12345678 w 0x9abcdef0
Source: https://github.com/mirror/busybox/blob/1_27_2/miscutils/devmem.c#L85
mmap MAP_SHARED
When mmapping /dev/mem, you likely want to use:
open("/dev/mem", O_RDWR | O_SYNC);
mmap(..., PROT_READ | PROT_WRITE, MAP_SHARED, ...)
MAP_SHARED makes writes go to physical memory immediately, which makes it easier to observe, and makes more sense for hardware register writes.
CONFIG_STRICT_DEVMEM and nopat
To use /dev/mem to view and modify regular RAM on kernel v4.9, you must fist:
disable CONFIG_STRICT_DEVMEM (set by default on Ubuntu 17.04)
pass the nopat kernel command line option for x86
IO ports still work without those.
See also: mmap of /dev/mem fails with invalid argument for virt_to_phys address, but address is page aligned
Cache flushing
If you try to write to RAM instead of a register, the memory may be cached by the CPU: How to flush the CPU cache for a region of address space in Linux? and I don't see a very portable / easy way to flush it or mark the region as uncacheable:
How to write kernel space memory (physical address) to a file using O_DIRECT?
How to flush the CPU cache for a region of address space in Linux?
Is it possible to allocate, in user space, a non cacheable block of memory on Linux?
So maybe /dev/mem can't be used reliably to pass memory buffers to devices?
This can't be observed in QEMU unfortunately, since QEMU does not simulate caches.
How to test it out
Now for the fun part. Here are a few cool setups:
Userland memory
allocate volatile variable on an userland process
get the physical address with /proc/<pid>/maps + /proc/<pid>/pagemap
modify the value at the physical address with devmem, and watch the userland process react
Kernelland memory
allocate kernel memory with kmalloc
get the physical address with virt_to_phys and pass it back to userland
modify the physical address with devmem
query the value from the kernel module
IO mem and QEMU virtual platform device
create a platform device with known physical register addresses
use devmem to write to the register
watch printfs come out of the virtual device in response
Bonus: determine the physical address for a virtual address
Is there any API for determining the physical address from virtual address in Linux?
You can map a device file to a user process memory using mmap(2) system call. Usually, device files are mappings of physical memory to the file system.
Otherwise, you have to write a kernel module which creates such a file or provides a way to map the needed memory to a user process.
Another way is remapping parts of /dev/mem to a user memory.
Edit:
Example of mmaping /dev/mem (this program must have access to /dev/mem, e.g. have root rights):
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Usage: %s <phys_addr> <offset>\n", argv[0]);
return 0;
}
off_t offset = strtoul(argv[1], NULL, 0);
size_t len = strtoul(argv[2], NULL, 0);
// Truncate offset to a multiple of the page size, or mmap will fail.
size_t pagesize = sysconf(_SC_PAGE_SIZE);
off_t page_base = (offset / pagesize) * pagesize;
off_t page_offset = offset - page_base;
int fd = open("/dev/mem", O_SYNC);
unsigned char *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, page_base);
if (mem == MAP_FAILED) {
perror("Can't map memory");
return -1;
}
size_t i;
for (i = 0; i < len; ++i)
printf("%02x ", (int)mem[page_offset + i]);
return 0;
}
I have been trying to look around in the linux source code for a structure/union that'd correspond to the PTE on x86 system with PAE disabled. So far I've found only the following in arch/x86/include/asm/page_32.h
typedef union {
pteval_t pte;
pteval_t pte_low;
} pte_t;
I'm a bit confused right now since I have the Intel Reference Manual Vol 3A open in front of me and nothing in that union corresponds to the dozen odd fields present in the PTE as the manual explains.
This might be a trivial question but for me it has become more like a stumbling block in the process of understanding memory management in the linux kernel.
EDIT: I have the 2.6.29 source with me
The pteval_t just treats the page table entry as an opaque blob - on the architecture you're looking at, it's just a 32 bit unsigned value.
The fields within the PTE are accessed using bitwise operators and masks - in the source I have handy (Linux 2.6.24), these are defined in include/asm-x86/pgtable_32.h. The fields you see in the Intel Reference Manual (most of which are single-bit flags) are defined here - for example:
#define _PAGE_PRESENT 0x001
#define _PAGE_RW 0x002
#define _PAGE_USER 0x004
#define _PAGE_PWT 0x008
#define _PAGE_PCD 0x010
#define _PAGE_ACCESSED 0x020
#define _PAGE_DIRTY 0x040
#define _PAGE_PSE 0x080 /* 4 MB (or 2MB) page, Pentium+, if present.. */
#define _PAGE_GLOBAL 0x100 /* Global TLB entry PPro+ */
#define _PAGE_UNUSED1 0x200 /* available for programmer */
#define _PAGE_UNUSED2 0x400
#define _PAGE_UNUSED3 0x800
I would recommend buying Understanding the Linux Kernel from O'REILLY, as well as Linux Device Drivers. And subscribing to LWN.net; though you can get a pretty good start from their kernel index page even without a subscription.
For the memory management, look on the index page for the "Memory management" section... and the "Large-memory systems" section. The latter has a few articles that talk about the move to four-level page tables that should be helpful in understanding this area of the code.