I've got a new symptom. I compiled GDB into the kernel so I could more easily examine what's what in my application space programs. In my simple test program (see below) I can step through until I get to the point that I use the mmap call. The call returns successfully but when I look at the pointer it returned I get:
$4 = 0x80126000 <Address 0x80126000 out of bounds>
finfo and vinfo look fine. Why would I get an out of bounds memory address from mmap? I tried putting a valid address in the call to mmap (rather than 0 to let the system pick) but then the thing just crashes the OS.
Stranger and stranger.... What would cause mmap to return and invalid address?
Code:
#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <linux/fb.h>#include <sys/mman.h>#include <sys/stat.h>#include <sys/types.h>typedef unsigned char S1D_INDEX;typedef unsigned long S1D_VALUE;char *fbp;struct stat my_stat;int main(){ int i=0, fbfd, x, y, err; long int location=0; unsigned long reg; unsigned short *regptr; size_t screensize; struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; off_t PageOffset, PageAddress, PhysAddr; printf ("sizeof(unsigned char): %d\n", sizeof(unsigned char)); printf ("sizeof(unsigned long): %d\n", sizeof(unsigned long)); /* Open the file for reading and writing */ fbfd = open("/dev/fb0", O_RDWR|O_NONBLOCK); if (!fbfd) { printf("Error: cannot open framebuffer device.\n"); exit(1); } printf("The framebuffer device was opened successfully.\n"); err = fstat(fbfd, &my_stat); printf ("mode = %o\n", my_stat.st_mode); /* Get fixed screen information */ if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) { perror ("ioctl"); printf("Error reading fixed information.\n"); exit(2); } /* Get variable screen information */ if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) { printf("Error reading variable information.\n"); exit(3); } /* Figure out the size of the screen in bytes */ screensize = (vinfo.xres * vinfo.yres * vinfo.bits_per_pixel) / 8; printf ("vinfo.xres = %d\n", vinfo.xres); printf ("vinfo.yres = %d\n", vinfo.yres); printf ("vinfo.bits_per_pixel = %d\n", vinfo.bits_per_pixel); printf ("screensize = 0x%x\n", screensize); printf ("PageSize (getpagesize): 0x%x\n", getpagesize()); /* Map the device to memory */ fbp = mmap(0, screensize, PROT_READ|PROT_WRITE, MAP_SHARED, fbfd, 0); if ((int)fbp == -1) { perror("mmap"); printf("\nError: failed to map framebuffer device to memory.\n"); exit(4); } printf("The framebuffer device was mapped to memory successfully.\n"); printf("Mapped to: 0x%x\n", fbp); *(fbp + 0x10) &= 0xff7fffff; // Enable printf("Enable\n"); *(fbp + 0x10) |= 0x00800000; // Clear printf("Clear\n"); printf("Start drawing\n"); for (i=0; i < 100; i++) { //printf ("location: %d\n", location); /* Where we are going to put the pixel */ //x = 100; //y = 100; x = i; y = i; /* Figure out where in memory to put the pixel */ location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) * finfo.line_length; //printf ("finfo.line_length: %d\n", finfo.line_length); //printf ("location: %d\n", location); *(fbp + location) = 150; /* Some blue */ *(fbp + location + 1) = 115; /* A little green */ *(fbp + location + 2) = 150; /* A lot of red */ *(fbp + location + 3) = 0; /* No transparency */ } *(fbp + 0x10) &= 0xff7fffff; // Enable printf("Done drawing\n"); munmap(fbp, screensize); printf("Unmapped\n"); close(fbfd); return 0;}