📄 btext.c
字号:
/* * BK Id: %F% %I% %G% %U% %#% *//* * Procedures for drawing on the screen early on in the boot process. * * Benjamin Herrenschmidt <benh@kernel.crashing.org> */#include <linux/config.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/init.h>#include <linux/version.h>#include <asm/sections.h>#include <asm/bootx.h>#include <asm/btext.h>#include <asm/prom.h>#include <asm/page.h>#include <asm/mmu.h>#include <asm/pgtable.h>#include <asm/io.h>#include <asm/processor.h>#define NO_SCROLL#ifndef NO_SCROLLstatic void scrollscreen(void);#endifstatic void draw_byte(unsigned char c, long locX, long locY);static void draw_byte_32(unsigned char *bits, unsigned long *base, int rb);static void draw_byte_16(unsigned char *bits, unsigned long *base, int rb);static void draw_byte_8(unsigned char *bits, unsigned long *base, int rb);static int g_loc_X;static int g_loc_Y;static int g_max_loc_X;static int g_max_loc_Y;unsigned long disp_BAT[2] __initdata = {0, 0};#define cmapsz (16*256)static unsigned char vga_font[cmapsz];int boot_text_mapped = 1;boot_infos_t *disp_bi;boot_infos_t fake_bi;extern char *klimit;/* * Powermac can use btext_* after boot for xmon, * chrp only uses it during early boot. */#ifdef CONFIG_XMON#define BTEXT __pmac#define BTDATA __pmacdata#else#define BTEXT __init#define BTDATA __initdata#endif /* CONFIG_XMON *//* * This is called only when we are booted via BootX. */void __initbtext_init(boot_infos_t *bi){ unsigned long offset = reloc_offset(); RELOC(g_loc_X) = 0; RELOC(g_loc_Y) = 0; RELOC(g_max_loc_X) = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8; RELOC(g_max_loc_Y) = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16; RELOC(disp_bi) = PTRUNRELOC(bi);}void __initbtext_welcome(boot_infos_t* bi){ unsigned long offset = reloc_offset(); unsigned long flags; unsigned long pvr; btext_drawstring(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n")); btext_drawstring(RELOC("\nlinked at : 0x")); btext_drawhex(KERNELBASE); btext_drawstring(RELOC("\nframe buffer at : 0x")); btext_drawhex((unsigned long)bi->dispDeviceBase); btext_drawstring(RELOC(" (phys), 0x")); btext_drawhex((unsigned long)bi->logicalDisplayBase); btext_drawstring(RELOC(" (log)")); btext_drawstring(RELOC("\nklimit : 0x")); btext_drawhex((unsigned long)RELOC(klimit)); btext_drawstring(RELOC("\nMSR : 0x")); __asm__ __volatile__ ("mfmsr %0" : "=r" (flags)); btext_drawhex(flags); __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr)); pvr >>= 16; if (pvr > 1) { btext_drawstring(RELOC("\nHID0 : 0x")); __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags)); btext_drawhex(flags); } if (pvr == 8 || pvr == 12 || pvr == 0x800c) { btext_drawstring(RELOC("\nICTC : 0x")); __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags)); btext_drawhex(flags); } btext_drawstring(RELOC("\n\n"));}/* Calc BAT values for mapping the display and store them * in disp_BAT. Those values are then used from head.S to map * the display during identify_machine() and MMU_Init() * * The display is mapped to virtual address 0xD0000000, rather * than 1:1, because some some CHRP machines put the frame buffer * in the region starting at 0xC0000000 (KERNELBASE). * This mapping is temporary and will disappear as soon as the * setup done by MMU_Init() is applied. * * For now, we align the BAT and then map 8Mb on 601 and 16Mb * on other PPCs. This may cause trouble if the framebuffer * is really badly aligned, but I didn't encounter this case * yet. */void __initbtext_prepare_BAT(void){ unsigned long offset = reloc_offset(); boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); unsigned long vaddr = KERNELBASE + 0x10000000; unsigned long addr; unsigned long lowbits; if (!RELOC(disp_bi)) { RELOC(boot_text_mapped) = 0; return; } addr = (unsigned long)bi->dispDeviceBase; if (!addr) { RELOC(boot_text_mapped) = 0; return; } if (PVR_VER(mfspr(PVR)) != 1) { /* 603, 604, G3, G4, ... */ lowbits = addr & ~0xFF000000UL; addr &= 0xFF000000UL; RELOC(disp_BAT[0]) = vaddr | (BL_16M<<2) | 2; RELOC(disp_BAT[1]) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW); } else { /* 601 */ lowbits = addr & ~0xFF800000UL; addr &= 0xFF800000UL; RELOC(disp_BAT[0]) = vaddr | (_PAGE_NO_CACHE | PP_RWXX) | 4; RELOC(disp_BAT[1]) = addr | BL_8M | 0x40; } bi->logicalDisplayBase = (void *) (vaddr + lowbits);}/* This function will enable the early boot text when doing OF booting. This * way, xmon output should work too */void __initbtext_setup_display(int width, int height, int depth, int pitch, unsigned long address){ unsigned long offset = reloc_offset(); boot_infos_t* bi; RELOC(disp_bi) = &fake_bi; bi = PTRRELOC((&fake_bi)); RELOC(g_loc_X) = 0; RELOC(g_loc_Y) = 0; RELOC(g_max_loc_X) = width / 8; RELOC(g_max_loc_Y) = height / 16; bi->logicalDisplayBase = (unsigned char *)address; bi->dispDeviceBase = (unsigned char *)address; bi->dispDeviceRowBytes = pitch; bi->dispDeviceDepth = depth; bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; bi->dispDeviceRect[2] = width; bi->dispDeviceRect[3] = height;}/* Here's a small text engine to use during early boot * or for debugging purposes * * todo: * * - build some kind of vgacon with it to enable early printk * - move to a separate file * - add a few video driver hooks to keep in sync with display * changes. */void __openfirmwaremap_boot_text(void){ unsigned long base, offset, size; if (disp_bi == 0) return; base = ((unsigned long) disp_bi->dispDeviceBase) & 0xFFFFF000UL; offset = ((unsigned long) disp_bi->dispDeviceBase) - base; size = disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3] + offset + disp_bi->dispDeviceRect[0]; disp_bi->logicalDisplayBase = ioremap(base, size); if (disp_bi->logicalDisplayBase == 0) return; disp_bi->logicalDisplayBase += offset; boot_text_mapped = 1;}/* Calc the base address of a given point (x,y) */static unsigned char * BTEXTcalc_base(boot_infos_t *bi, int x, int y){ unsigned char *base; base = bi->logicalDisplayBase; if (base == 0) base = bi->dispDeviceBase; base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3); base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes; return base;}/* Adjust the display to a new resolution */voidbtext_update_display(unsigned long phys, int width, int height, int depth, int pitch){ if (disp_bi == 0) return; /* check it's the same frame buffer (within 256MB) */ if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xf0000000) return; disp_bi->dispDeviceBase = (__u8 *) phys; disp_bi->dispDeviceRect[0] = 0; disp_bi->dispDeviceRect[1] = 0; disp_bi->dispDeviceRect[2] = width; disp_bi->dispDeviceRect[3] = height; disp_bi->dispDeviceDepth = depth; disp_bi->dispDeviceRowBytes = pitch; if (boot_text_mapped) { iounmap(disp_bi->logicalDisplayBase); boot_text_mapped = 0; } map_boot_text(); g_loc_X = 0; g_loc_Y = 0; g_max_loc_X = width / 8; g_max_loc_Y = height / 16;}void BTEXT btext_clearscreen(void){ unsigned long offset = reloc_offset(); boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3)) >> 2; int i,j; for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) { unsigned long *ptr = base; for(j=width; j; --j) *(ptr++) = 0; base += (bi->dispDeviceRowBytes >> 2); }}__inline__ void dcbst(const void* addr){ __asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr));}void BTEXT btext_flushscreen(void){ unsigned long offset = reloc_offset(); boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3)) >> 2; int i,j;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -