From: notaz Date: Wed, 28 Jul 2010 13:16:21 +0000 (+0300) Subject: add prep tool and common X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=ginge.git;a=commitdiff_plain;h=3adc9ccb6566130bde29eeaf5c126f28c57c57d5 add prep tool and common --- diff --git a/common/cmn.c b/common/cmn.c new file mode 100644 index 0000000..9f802ba --- /dev/null +++ b/common/cmn.c @@ -0,0 +1,43 @@ +#ifdef LOADER +#include "../loader/realfuncs.h" +#endif +#include +#include +#include + +#include "cmn.h" + +int make_local_path(char *buf, size_t size, const char *file) +{ + ssize_t ret; + char *p; + + ret = readlink("/proc/self/exe", buf, size - 1); + if (ret < 0) { + perror("readlink"); + goto err; + } + buf[ret] = 0; + + p = strrchr(buf, '/'); + if (p == NULL) + goto err; + p++; + + if (strstr(p, ".so")) { + p = getenv("GINGE_ROOT"); + if (p == NULL) + goto err; + strcpy(buf, p); + p = buf + strlen(buf); + } + + snprintf(p, size - (p - buf), "%s", file); + + return 0; + +err: + fprintf(stderr, "ginge: can't determine root, buf: \"%s\"\n", buf); + return -1; +} + diff --git a/common/cmn.h b/common/cmn.h new file mode 100644 index 0000000..9257e11 --- /dev/null +++ b/common/cmn.h @@ -0,0 +1,3 @@ +#include + +int make_local_path(char *buf, size_t size, const char *file); diff --git a/common/fbdev.c b/common/fbdev.c new file mode 100644 index 0000000..069dc6e --- /dev/null +++ b/common/fbdev.c @@ -0,0 +1,180 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fbdev.h" + +#define FBDEV_MAX_BUFFERS 3 + +struct vout_fbdev { + int fd; + void *mem; + size_t mem_size; + struct fb_var_screeninfo fbvar_old; + struct fb_var_screeninfo fbvar_new; + int buffer_write; + void *buffers[FBDEV_MAX_BUFFERS]; + int buffer_count; +}; + +void *vout_fbdev_flip(struct vout_fbdev *fbdev) +{ + int draw_buf; + + if (fbdev->buffer_count < 2) + return fbdev->mem; + + draw_buf = fbdev->buffer_write; + fbdev->buffer_write++; + if (fbdev->buffer_write >= fbdev->buffer_count) + fbdev->buffer_write = 0; + + fbdev->fbvar_new.yoffset = fbdev->fbvar_old.yres * draw_buf; + + ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new); + + return fbdev->buffers[fbdev->buffer_write]; +} + +void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev) +{ + int arg = 0; + ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &arg); +} + +void vout_fbdev_clear(struct vout_fbdev *fbdev) +{ + memset(fbdev->mem, 0, fbdev->mem_size); +} + +struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int no_dblbuf) +{ + struct vout_fbdev *fbdev; + int i, ret; + + fbdev = calloc(1, sizeof(*fbdev)); + if (fbdev == NULL) + return NULL; + + fbdev->fd = open(fbdev_name, O_RDWR, 0); + if (fbdev->fd == -1) { + fprintf(stderr, "%s: ", fbdev_name); + perror("open"); + goto fail_open; + } + + ret = ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->fbvar_old); + if (ret == -1) { + perror("FBIOGET_VSCREENINFO ioctl"); + goto fail; + } + + fbdev->fbvar_new = fbdev->fbvar_old; + printf("%s: %ix%i@%d\n", fbdev_name, fbdev->fbvar_old.xres, fbdev->fbvar_old.yres, + fbdev->fbvar_old.bits_per_pixel); + *w = fbdev->fbvar_old.xres; + *h = fbdev->fbvar_old.yres; + fbdev->buffer_count = FBDEV_MAX_BUFFERS; // be optimistic + if (no_dblbuf) + fbdev->buffer_count = 1; + + if (fbdev->fbvar_new.bits_per_pixel != 16) { + printf(" switching to 16bpp\n"); + fbdev->fbvar_new.bits_per_pixel = 16; + ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); + if (ret == -1) { + perror("FBIOPUT_VSCREENINFO ioctl"); + goto fail; + } + } + + if (fbdev->fbvar_new.yres_virtual < fbdev->fbvar_old.yres * fbdev->buffer_count) { + fbdev->fbvar_new.yres_virtual = fbdev->fbvar_old.yres * fbdev->buffer_count; + ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); + if (ret == -1) { + fbdev->buffer_count = 1; + fprintf(stderr, "Warning: failed to increase virtual resolution, " + "doublebuffering disabled\n"); + } + } + + fbdev->mem_size = *w * *h * 2 * fbdev->buffer_count; + fbdev->mem = mmap(0, fbdev->mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0); + if (fbdev->mem == MAP_FAILED && fbdev->buffer_count > 1) { + fprintf(stderr, "Warning: can't map %zd bytes, doublebuffering disabled\n", fbdev->mem_size); + fbdev->mem_size = *w * *h * 2; + fbdev->buffer_count = 1; + fbdev->mem = mmap(0, fbdev->mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0); + } + if (fbdev->mem == MAP_FAILED) { + perror("mmap framebuffer"); + goto fail; + } + memset(fbdev->mem, 0, fbdev->mem_size); + for (i = 0; i < fbdev->buffer_count; i++) + fbdev->buffers[i] = (char *)fbdev->mem + i * *w * *h * 2; + + // some checks + ret = 0; + ret = ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &ret); + if (ret != 0) + fprintf(stderr, "Warning: vsync doesn't seem to be supported\n"); + + if (fbdev->buffer_count > 1) { + fbdev->buffer_write = 0; + fbdev->fbvar_new.yoffset = fbdev->fbvar_old.yres * (fbdev->buffer_count - 1); + ret = ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new); + if (ret != 0) { + fbdev->buffer_count = 1; + fprintf(stderr, "Warning: can't pan display, doublebuffering disabled\n"); + } + } + + printf("fbdev initialized.\n"); + return fbdev; + +fail: + close(fbdev->fd); +fail_open: + free(fbdev); + return NULL; +} + +void vout_fbdev_finish(struct vout_fbdev *fbdev) +{ + ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_old); + if (fbdev->mem != MAP_FAILED) + munmap(fbdev->mem, fbdev->mem_size); + if (fbdev->fd >= 0) + close(fbdev->fd); + fbdev->mem = NULL; + fbdev->fd = -1; + free(fbdev); +} + +#if 0 +void *g_screen_ptr; +int main() +{ + int w, h; + vout_fbdev_init(&w, &h); + //while (1) + { + memset(g_screen_ptr, 0xff, fbdev_mem_size / 2); + plat_video_wait_vsync(); + plat_video_flip(); + memset(g_screen_ptr, 0x00, fbdev_mem_size / 2); + usleep(8000); +// plat_video_wait_vsync(); + plat_video_flip(); + } +} +#endif diff --git a/common/fbdev.h b/common/fbdev.h new file mode 100644 index 0000000..9e5d433 --- /dev/null +++ b/common/fbdev.h @@ -0,0 +1,7 @@ +struct vout_fbdev; + +struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int no_dblbuf); +void *vout_fbdev_flip(struct vout_fbdev *fbdev); +void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev); +void vout_fbdev_clear(struct vout_fbdev *fbdev); +void vout_fbdev_finish(struct vout_fbdev *fbdev); diff --git a/common/host_fb.c b/common/host_fb.c new file mode 100644 index 0000000..92cde57 --- /dev/null +++ b/common/host_fb.c @@ -0,0 +1,27 @@ +#ifdef LOADER +#include "../loader/realfuncs.h" +#endif + +#include "fbdev.c" +#include "host_fb.h" + +static struct vout_fbdev *fbdev; + +int host_video_init(int *stride, int no_dblbuf) +{ + const char *fbdev_name; + int w, h; + + fbdev_name = getenv("FBDEV"); + if (fbdev_name == NULL) + fbdev_name = "/dev/fb1"; + + fbdev = vout_fbdev_init(fbdev_name, &w, &h, no_dblbuf); + *stride = w * 2; + return (fbdev != 0) ? 0 : -1; +} + +void *host_video_flip(void) +{ + return vout_fbdev_flip(fbdev); +} diff --git a/common/host_fb.h b/common/host_fb.h new file mode 100644 index 0000000..bd739d4 --- /dev/null +++ b/common/host_fb.h @@ -0,0 +1,3 @@ +int host_video_init(int *stride, int no_dblbuf); +void *host_video_flip(void); + diff --git a/common/wiz_video.c b/common/wiz_video.c new file mode 100644 index 0000000..4395683 --- /dev/null +++ b/common/wiz_video.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static volatile unsigned short *memregs; +static volatile unsigned long *memregl; +static int memdev = -1; + +#define FB_BUF_COUNT 4 +static unsigned int fb_paddr[FB_BUF_COUNT]; +static int fb_work_buf; +static int fbdev = -1; + +static void *gp2x_screens[FB_BUF_COUNT]; +static void *g_screen_ptr; + + +static void vout_gp2x_flip(void) +{ + memregl[0x406C>>2] = fb_paddr[fb_work_buf]; + memregl[0x4058>>2] |= 0x10; + + fb_work_buf++; + if (fb_work_buf >= FB_BUF_COUNT) + fb_work_buf = 0; + g_screen_ptr = gp2x_screens[fb_work_buf]; +} + +static int vout_gp2x_init(void) +{ + struct fb_fix_screeninfo fbfix; + int i, ret; + + memdev = open("/dev/mem", O_RDWR); + if (memdev == -1) { + perror("open(/dev/mem) failed"); + exit(1); + } + + memregs = mmap(0, 0x20000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000); + if (memregs == MAP_FAILED) { + perror("mmap(memregs) failed"); + exit(1); + } + memregl = (volatile void *)memregs; + + fbdev = open("/dev/fb0", O_RDWR); + if (fbdev < 0) { + perror("can't open fbdev"); + exit(1); + } + + ret = ioctl(fbdev, FBIOGET_FSCREENINFO, &fbfix); + if (ret == -1) { + perror("ioctl(fbdev) failed"); + exit(1); + } + + printf("framebuffer: \"%s\" @ %08lx\n", fbfix.id, fbfix.smem_start); + fb_paddr[0] = fbfix.smem_start; + + gp2x_screens[0] = mmap(0, 320*240*2*FB_BUF_COUNT, PROT_READ|PROT_WRITE, + MAP_SHARED, memdev, fb_paddr[0]); + if (gp2x_screens[0] == MAP_FAILED) + { + perror("mmap(gp2x_screens) failed"); + exit(1); + } + memset(gp2x_screens[0], 0, 320*240*2*FB_BUF_COUNT); + + printf(" %p -> %08x\n", gp2x_screens[0], fb_paddr[0]); + for (i = 1; i < FB_BUF_COUNT; i++) + { + fb_paddr[i] = fb_paddr[i-1] + 320*240*2; + gp2x_screens[i] = (char *)gp2x_screens[i-1] + 320*240*2; + printf(" %p -> %08x\n", gp2x_screens[i], fb_paddr[i]); + } + fb_work_buf = 0; + g_screen_ptr = gp2x_screens[0]; + + return 0; +} + +void vout_gp2x_finish(void) +{ + memregl[0x406C>>2] = fb_paddr[0]; + memregl[0x4058>>2] |= 0x10; + close(fbdev); + + munmap((void *)memregs, 0x20000); + close(memdev); +} + diff --git a/prep/Makefile b/prep/Makefile new file mode 100644 index 0000000..368dc0e --- /dev/null +++ b/prep/Makefile @@ -0,0 +1,16 @@ +CC = $(CROSS_COMPILE)gcc +CFLAGS += -Wall -O2 +LDFLAGS = -s -O2 + +vpath %.c = ../common/ + +TARGET = ginge_prep +OBJS = main.o host_fb.o cmn.o + +all: $(TARGET) + +ginge_prep: $(OBJS) + $(CC) -o $@ $^ $(LDFLAGS) + +clean: + $(RM) $(TARGET) $(OBJS) diff --git a/prep/font.c b/prep/font.c new file mode 100644 index 0000000..bc1f764 --- /dev/null +++ b/prep/font.c @@ -0,0 +1,68 @@ +static const unsigned char fontdata8x8[64*16] = +{ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3C,0x42,0x99,0xBD,0xBD,0x99,0x42,0x3C,0x3C,0x42,0x81,0x81,0x81,0x81,0x42,0x3C, + 0xFE,0x82,0x8A,0xD2,0xA2,0x82,0xFE,0x00,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x64,0x74,0x7C,0x38,0x00,0x00, + 0x80,0xC0,0xF0,0xFC,0xF0,0xC0,0x80,0x00,0x01,0x03,0x0F,0x3F,0x0F,0x03,0x01,0x00, + 0x18,0x3C,0x7E,0x18,0x7E,0x3C,0x18,0x00,0xEE,0xEE,0xEE,0xCC,0x00,0xCC,0xCC,0x00, + 0x00,0x00,0x30,0x68,0x78,0x30,0x00,0x00,0x00,0x38,0x64,0x74,0x7C,0x38,0x00,0x00, + 0x3C,0x66,0x7A,0x7A,0x7E,0x7E,0x3C,0x00,0x0E,0x3E,0x3A,0x22,0x26,0x6E,0xE4,0x40, + 0x18,0x3C,0x7E,0x3C,0x3C,0x3C,0x3C,0x00,0x3C,0x3C,0x3C,0x3C,0x7E,0x3C,0x18,0x00, + 0x08,0x7C,0x7E,0x7E,0x7C,0x08,0x00,0x00,0x10,0x3E,0x7E,0x7E,0x3E,0x10,0x00,0x00, + 0x58,0x2A,0xDC,0xC8,0xDC,0x2A,0x58,0x00,0x24,0x66,0xFF,0xFF,0x66,0x24,0x00,0x00, + 0x00,0x10,0x10,0x38,0x38,0x7C,0xFE,0x00,0xFE,0x7C,0x38,0x38,0x10,0x10,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x18,0x00,0x18,0x18,0x00, + 0x6C,0x6C,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x7C,0x28,0x7C,0x28,0x00,0x00, + 0x10,0x38,0x60,0x38,0x0C,0x78,0x10,0x00,0x40,0xA4,0x48,0x10,0x24,0x4A,0x04,0x00, + 0x18,0x34,0x18,0x3A,0x6C,0x66,0x3A,0x00,0x18,0x18,0x20,0x00,0x00,0x00,0x00,0x00, + 0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x00,0x0C,0x06,0x06,0x06,0x06,0x06,0x0C,0x00, + 0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00, + 0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x00,0x00, + 0x38,0x4C,0xC6,0xC6,0xC6,0x64,0x38,0x00,0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00, + 0x7C,0xC6,0x0E,0x3C,0x78,0xE0,0xFE,0x00,0x7E,0x0C,0x18,0x3C,0x06,0xC6,0x7C,0x00, + 0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x00,0xFC,0xC0,0xFC,0x06,0x06,0xC6,0x7C,0x00, + 0x3C,0x60,0xC0,0xFC,0xC6,0xC6,0x7C,0x00,0xFE,0xC6,0x0C,0x18,0x30,0x30,0x30,0x00, + 0x78,0xC4,0xE4,0x78,0x86,0x86,0x7C,0x00,0x7C,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, + 0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x18,0x18,0x30, + 0x1C,0x38,0x70,0xE0,0x70,0x38,0x1C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, + 0x70,0x38,0x1C,0x0E,0x1C,0x38,0x70,0x00,0x7C,0xC6,0xC6,0x1C,0x18,0x00,0x18,0x00, + 0x3C,0x42,0x99,0xA1,0xA5,0x99,0x42,0x3C,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00, + 0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00,0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00, + 0xF8,0xCC,0xC6,0xC6,0xC6,0xCC,0xF8,0x00,0xFE,0xC0,0xC0,0xFC,0xC0,0xC0,0xFE,0x00, + 0xFE,0xC0,0xC0,0xFC,0xC0,0xC0,0xC0,0x00,0x3E,0x60,0xC0,0xCE,0xC6,0x66,0x3E,0x00, + 0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x7E,0x00, + 0x06,0x06,0x06,0x06,0xC6,0xC6,0x7C,0x00,0xC6,0xCC,0xD8,0xF0,0xF8,0xDC,0xCE,0x00, + 0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0x00, + 0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, + 0xFC,0xC6,0xC6,0xC6,0xFC,0xC0,0xC0,0x00,0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x7A,0x00, + 0xFC,0xC6,0xC6,0xCE,0xF8,0xDC,0xCE,0x00,0x78,0xCC,0xC0,0x7C,0x06,0xC6,0x7C,0x00, + 0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, + 0xC6,0xC6,0xC6,0xEE,0x7C,0x38,0x10,0x00,0xC6,0xC6,0xD6,0xFE,0xFE,0xEE,0xC6,0x00, + 0xC6,0xEE,0x3C,0x38,0x7C,0xEE,0xC6,0x00,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00, + 0xFE,0x0E,0x1C,0x38,0x70,0xE0,0xFE,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00, + 0x60,0x60,0x30,0x18,0x0C,0x06,0x06,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00, + 0x18,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, + 0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x3E,0x66,0x66,0x3C,0x00, + 0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x00, + 0x06,0x3E,0x66,0x66,0x66,0x66,0x3E,0x00,0x00,0x3C,0x66,0x66,0x7E,0x60,0x3C,0x00, + 0x1C,0x30,0x78,0x30,0x30,0x30,0x30,0x00,0x00,0x3E,0x66,0x66,0x66,0x3E,0x06,0x3C, + 0x60,0x7C,0x76,0x66,0x66,0x66,0x66,0x00,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x00, + 0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x38,0x60,0x60,0x66,0x6C,0x78,0x6C,0x66,0x00, + 0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0xEC,0xFE,0xFE,0xFE,0xD6,0xC6,0x00, + 0x00,0x7C,0x76,0x66,0x66,0x66,0x66,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00, + 0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60,0x00,0x3E,0x66,0x66,0x66,0x3E,0x06,0x06, + 0x00,0x7E,0x70,0x60,0x60,0x60,0x60,0x00,0x00,0x3C,0x60,0x3C,0x06,0x66,0x3C,0x00, + 0x30,0x78,0x30,0x30,0x30,0x30,0x1C,0x00,0x00,0x66,0x66,0x66,0x66,0x6E,0x3E,0x00, + 0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0xC6,0xD6,0xFE,0xFE,0x7C,0x6C,0x00, + 0x00,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,0x00,0x66,0x66,0x66,0x66,0x3E,0x06,0x3C, + 0x00,0x7E,0x0C,0x18,0x30,0x60,0x7E,0x00,0x0E,0x18,0x0C,0x38,0x0C,0x18,0x0E,0x00, + 0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x70,0x18,0x30,0x1C,0x30,0x18,0x70,0x00, + 0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x10,0x28,0x10,0x54,0xAA,0x44,0x00,0x00, +}; + diff --git a/prep/main.c b/prep/main.c new file mode 100644 index 0000000..7cc4337 --- /dev/null +++ b/prep/main.c @@ -0,0 +1,427 @@ +// vim:shiftwidth=2:expandtab +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../common/host_fb.h" +#include "../common/cmn.h" + +#define PFX "ging_prep: " +#define LOADER_STATIC "ginge_sloader" +#define LOADER_DYNAMIC "ginge_dyn.sh" +#define LAUNCHER "gp2xmenu" + +#include "font.c" + +static void *fb_mem; +static int fb_stride; +static int fb_x, fb_y; + +static char *sskip(char *p) +{ + while (p && *p && isspace(*p)) + p++; + return p; +} + +static char *cskip(char *p) +{ + while (p && *p && !isspace(*p)) + p++; + return p; +} + +static void fb_syms_out(void *fbi, int x, int y, int dotsz, int stride, const char *text, int count) +{ + int v = -1, n = 0, *p; + int i, l; + char *fb; + + fb = (char *)fbi + x * dotsz + y * stride; + + for (i = 0; i < count; i++) + { + for (l = 0; l < 8; l++) + { + #define pix(fdmask,add) \ + p = (fontdata8x8[((text[i])*8)+l] & fdmask) ? &v : &n; \ + memcpy(fb + l*stride + add*dotsz, p, dotsz) + pix(0x80, 0); + pix(0x40, 1); + pix(0x20, 2); + pix(0x10, 3); + pix(0x08, 4); + pix(0x04, 5); + pix(0x02, 6); + pix(0x01, 7); + #undef pix + } + fb += dotsz * 8; + } +} + +// FIXME: y overrun +static void fb_text_out(char *text) +{ + int dotsz = 2, w = 320; // hardcoded for now + char *p, *pe; + int l; + + if (fb_mem == NULL) + return; + + p = text; + while (*p) { + for (; *p && isspace(*p); p++) { + if (*p == '\n' || fb_x + dotsz * 8 > w) { + fb_x = 4; + fb_y += 8; + } + if (*p >= 0x20) + fb_x += 8; + } + + pe = cskip(p); + l = pe - p; + if (fb_x + 8 * l > w) { + fb_x = 4; + fb_y += 8; + } + fb_syms_out(fb_mem, fb_x, fb_y, dotsz, fb_stride, p, l); + fb_x += 8 * l; + p = pe; + } +} + +static void fb_text_init(void) +{ + int ret = host_video_init(&fb_stride, 1); + if (ret == 0) + fb_mem = host_video_flip(); + fb_x = 4; + fb_y = 4; +} + +static void fbprintf(int is_err, const char *format, ...) +{ + va_list ap; + char buff[512]; + + va_start(ap, format); + vsnprintf(buff, sizeof(buff), format, ap); + va_end(ap); + fputs(buff, is_err ? stderr : stdout); + + fb_text_out(buff); +} + +#define msg(fmt, ...) fbprintf(0, fmt, #__VA_ARGS__) +#define err(fmt, ...) fbprintf(1, fmt, #__VA_ARGS__) + +static int id_elf(const char *fname) +{ + Elf32_Ehdr hdr; + Elf32_Phdr *phdr = NULL; + FILE *fi; + int i, ret = 0; + + fi = fopen(fname, "rb"); + if (fi == NULL) { + err("open %s: ", fname); + perror(""); + return -1; + } + + if (fread(&hdr, 1, sizeof(hdr), fi) != sizeof(hdr)) + goto out; + + if (memcmp(hdr.e_ident, ELFMAG "\x01\x01", SELFMAG + 2) != 0) + goto out; + + if (hdr.e_phentsize != sizeof(Elf32_Phdr) || hdr.e_phnum == 0) + goto out; + + phdr = malloc(hdr.e_phnum * hdr.e_phentsize); + if (phdr == NULL) + goto out; + + if (fread(phdr, hdr.e_phentsize, hdr.e_phnum, fi) != hdr.e_phnum) + goto out; + + ret = 1; + + // do what 'file' does - check for PT_INTERP in program headers + for (i = 0; i < hdr.e_phnum; i++) { + if (phdr[i].p_type == PT_INTERP) { + ret = 2; + break; + } + } + +out: + fclose(fi); + free(phdr); + return ret; +} + +static void dump_args(FILE *fout, int argc, char * const argv[]) +{ + const char *p; + int i; + + for (i = 0; i < argc; i++) { + if (i != 0) + fputc(' ', fout); + fputc('"', fout); + + for (p = argv[i]; *p != 0; p++) { + if (*p == '"') + fputc('\\', fout); + fputc(*p, fout); + } + + fputc('"', fout); + } +} + +static char *get_arg(char *d, size_t size, char *p) +{ + char *pe; + int len; + + p = sskip(p); + pe = cskip(p); + len = pe - p; + + if (len > size - 1) { + err(PFX "get_arg: buff to small: %d/%d\n", len, size); + len = size - 1; + } + strncpy(d, p, len); + d[len] = 0; + + return sskip(pe); +} + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +#define CB_ENTRY(x) { x, sizeof(x) - 1 } +const struct { + const char *name; + int len; +} conv_blacklist[] = { + CB_ENTRY("insmod"), + CB_ENTRY("modprobe"), + CB_ENTRY("umount"), + CB_ENTRY("./cpuctrl_tiny"), +}; + +static int cmd_in_blacklist(char *cmd) +{ + int i; + + cmd = sskip(cmd); + for (i = 0; i < ARRAY_SIZE(conv_blacklist); i++) + if (strncmp(cmd, conv_blacklist[i].name, conv_blacklist[i].len) == 0) + return 1; + + return 0; +} + +int main(int argc, char *argv[]) +{ + static const char out_script[] = "/tmp/ginge_conv.sh"; + char root_path[512], cwd[512]; + int have_cramfs = 0; + int rerun_gp2xmenu = 1; + FILE *fin, *fout; + int ret; + + fb_text_init(); + + if (argc < 2) { + err("usage: %s [args]\n", argv[0]); + return 1; + } + + if (getcwd(cwd, sizeof(cwd)) == NULL) { + err(PFX "failed to get cwd\n"); + return 1; + } + + ret = make_local_path(root_path, sizeof(root_path), ""); + if (ret != 0) { + err(PFX "failed to generate root path\n"); + return 1; + } + + fout = fopen(out_script, "w"); + if (fout == NULL) { + perror("can't open output script"); + return 1; + } + + fprintf(fout, "#!/bin/sh\n"); + + ret = id_elf(argv[1]); + if (ret == 1 || ret == 2) { + if (cmd_in_blacklist(argv[1])) { + fprintf(stderr, "blacklisted: %s\n", argv[1]); + goto no_in_script; + } + } + + switch (ret) { + case 0: + break; + + case 1: + fprintf(fout, "op_runfbapp %s%s ", root_path, LOADER_STATIC); + dump_args(fout, argc - 1, &argv[1]); + fprintf(fout, "\n"); + goto no_in_script; + + case 2: + fprintf(fout, "op_runfbapp %s%s \"%s\" ", root_path, LOADER_DYNAMIC, root_path); + dump_args(fout, argc - 1, &argv[1]); + fprintf(fout, "\n"); + goto no_in_script; + + default: + return 1; + } + + // assume script + fin = fopen(argv[1], "r"); + if (fin == NULL) + return 1; + + while (1) { + char buff[512], fname[512], *p, *p2; + + p = fgets(buff, sizeof(buff), fin); + if (p == NULL) + break; + p = sskip(p); + + if (p[0] == '#' && p[1] == '!') + continue; + + if (*p == 0) { + fputs("\n", fout); + continue; + } + + // things we are sure we want to pass + if (*p == '#' || strncmp(p, "export ", 7) == 0) + goto pass; + + // hmh.. + if (strncmp(p, "exec ", 5) == 0) + p = sskip(p + 5); + + // blacklist some stuff + if (strncmp(p, "/sbin/", 6) == 0) + p2 = p + 6; + else if (strncmp(p, "/bin/", 5) == 0) + p2 = p + 5; + else + p2 = p; + if (strncmp(p2, "mount ", 6) == 0) { + p2 = sskip(p2 + 6); + // cramfs stuff? + if (strstr(p2, "cramfs")) { + while (*p2 == '-') { + // skip option + p2 = sskip(cskip(p2)); + p2 = sskip(cskip(p2)); + } + if (*p2 == 0) { + err(PFX "cramfs: missing mount file in \"%s\"?\n", p); + continue; + } + p2 = get_arg(fname, sizeof(fname), p2); + if (*p2 == 0) { + err(PFX "cramfs: missing mount point in \"%s\"?\n", p); + continue; + } + get_arg(buff, sizeof(buff), p2); + fprintf(fout, "if [ `ls %s | wc -l` -eq 0 ]; then\n", buff); + fprintf(fout, " rmdir \"%s\"\n", buff); // cramfsck doesn't want it + fprintf(fout, " %stools/cramfsck -x \"%s\" \"%s\"\n", root_path, buff, fname); + fprintf(fout, "fi\n"); + have_cramfs = 1; + } + continue; + } + if (cmd_in_blacklist(p2)) + continue; + + // cd? + if (strncmp(p, "cd ", 3) == 0) { + get_arg(fname, sizeof(fname), p + 3); + if (strncmp(fname, "/usr/gp2x", 9) == 0) + continue; + ret = chdir(fname); + if (ret != 0) { + err("%s: ", fname); + perror(""); + } + } + + // trying to run something from cwd? + if ((p[0] == '.' && p[1] == '/') || *p == '/') { + get_arg(fname, sizeof(fname), p); + p2 = strrchr(fname, '/'); + if (p2 != NULL && strcmp(p2 + 1, "gp2xmenu") == 0) + continue; + + ret = id_elf(fname); + switch (ret) { + case 1: + printf(PFX "prefixing as static: %s", p); + fprintf(fout, "op_runfbapp %s%s ", root_path, LOADER_STATIC); + break; + + case 2: + printf(PFX "prefixing as dynamic: %s", p); + fprintf(fout, "op_runfbapp %s%s \"%s\" ", root_path, LOADER_DYNAMIC, root_path); + break; + + default: + break; + } + } + +pass: + fputs(p, fout); + } + + fclose(fin); + +no_in_script: + if (rerun_gp2xmenu) { + fprintf(fout, "cd %s\n", root_path); + fprintf(fout, "exec %s%s\n", root_path, LAUNCHER); + } + + fclose(fout); + + msg("starting script..\n"); + if (have_cramfs) + msg("\nsome files need to be unpacked, this may tike a few minutes.\n" + "Please wait at least while SD LED is active.\n"); + system("echo ---; cat /tmp/ginge_conv.sh; echo ---"); + chmod(out_script, S_IRWXU|S_IRWXG|S_IRWXO); + chdir(cwd); + execlp(out_script, out_script, NULL); + perror("run out_script"); + + return 1; +} +