diff --git a/Makefile b/Makefile index 056d7a2..042ab99 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,6 @@ CFLAGS=-Wall -Wextra -ffreestanding -march=armv8-a+crc -mcpu=cortex-a53 DEBUG_FLAGS += -g -Og -DDEBUG -fno-omit-frame-pointer -fno-inline LDSCRIPT=rpi3.ld -OBJS=crt0.o uart.o hello.o gasmsrc=$(wildcard *.S) gasmobj=$(gasmsrc:%.S=%.o) csrc=$(wildcard *.c) @@ -18,12 +17,15 @@ KERNEL=kernel.bin all:$(KERNEL) -kernel.elf: $(cobj) $(gasmobj) $(LDSCRIPT) - $(LD) $(LDFLAGS) -o $@ $(gasmobj) $(cobj) -T$(LDSCRIPT) -Map kernel.map +kernel.elf: $(cobj) $(gasmobj) font_psf.o $(LDSCRIPT) + $(LD) $(LDFLAGS) -o $@ $(gasmobj) $(cobj) font_psf.o -T$(LDSCRIPT) -Map kernel.map $(KERNEL): kernel.elf $(CROSS)objcopy -O binary $< $@ +font_psf.o: font.psf + $(LD) -r -b binary -o font_psf.o font.psf + clean: rm -rf $(cobj) $(gasmobj) $(deps) *.bin *.elf *.map diff --git a/fb.c b/fb.c index 3cd0aec..3af3682 100644 --- a/fb.c +++ b/fb.c @@ -12,38 +12,55 @@ #define MBOX_TAG_FBSETPIXORD 0x48006 #define MBOX_TAG_FBSETOFF 0x48009 -unsigned char *init_fb(struct fbst *fb) { +/* PC Screen Font as used by Linux Console */ +typedef struct { + unsigned int magic; + unsigned int version; + unsigned int headersize; + unsigned int flags; + unsigned int numglyph; + unsigned int bytesperglyph; + unsigned int height; + unsigned int width; + unsigned char glyphs; +} __attribute__((packed)) psf_t; +extern volatile unsigned char _binary_font_psf_start; + +static struct fbst fb; + +unsigned char *fb_init() +{ // sending many tags at once - mbox[0] = 35 * 4; - mbox[1] = MBOX_REQUEST; - mbox[2] = MBOX_TAG_FBSETPHYS; // set phy wh - mbox[3] = 8; - mbox[4] = 0; - mbox[5] = 1920; // FrameBufferInfo.width - mbox[6] = 1080; // FrameBufferInfo.height - mbox[7] = MBOX_TAG_FBSETVIRT; // set virt wh - mbox[8] = 8; - mbox[9] = 0; - mbox[10] = 1920; // FrameBufferInfo.virtual_width - mbox[11] = 1080; // FrameBufferInfo.virtual_height + mbox[0] = 35 * 4; + mbox[1] = MBOX_REQUEST; + mbox[2] = MBOX_TAG_FBSETPHYS; // set phy wh + mbox[3] = 8; + mbox[4] = 0; + mbox[5] = 1920; // FrameBufferInfo.width + mbox[6] = 1080; // FrameBufferInfo.height + mbox[7] = MBOX_TAG_FBSETVIRT; // set virt wh + mbox[8] = 8; + mbox[9] = 0; + mbox[10] = 1920; // FrameBufferInfo.virtual_width + mbox[11] = 1080; // FrameBufferInfo.virtual_height mbox[12] = MBOX_TAG_FBSETOFF; // set virt offset mbox[13] = 8; mbox[14] = 0; - mbox[15] = 0; // FrameBufferInfo.x_offset - mbox[16] = 0; // FrameBufferInfo.y.offset + mbox[15] = 0; // FrameBufferInfo.x_offset + mbox[16] = 0; // FrameBufferInfo.y.offset mbox[17] = MBOX_TAG_FBSETDEPTH; // set depth mbox[18] = 4; mbox[19] = 0; - mbox[20] = 32; // FrameBufferInfo.depth + mbox[20] = 32; // FrameBufferInfo.depth mbox[21] = MBOX_TAG_FBSETPIXORD; // set pixel order mbox[22] = 4; mbox[23] = 0; - mbox[24] = 1; // RGB, not BGR preferably + mbox[24] = 1; // RGB, not BGR preferably mbox[25] = MBOX_TAG_FBALLOC; // get framebuffer, gets alignment on request mbox[26] = 8; mbox[27] = 0; - mbox[28] = 4096; // FrameBufferInfo.pointer - mbox[29] = 0; // FrameBufferInfo.size + mbox[28] = 4096; // FrameBufferInfo.pointer + mbox[29] = 0; // FrameBufferInfo.size mbox[30] = MBOX_TAG_FBGETPITCH; // get pitch mbox[31] = 4; mbox[32] = 0; @@ -52,15 +69,64 @@ unsigned char *init_fb(struct fbst *fb) { if (mbox_call(MBOX_CH_PROP, mbox) == 0 && mbox[20] == 32 && mbox[28] != 0) { mbox[28] &= 0x3FFFFFFF; // convert GPU address to ARM address - fb->width = mbox[5]; // get actual physical width - fb->height = mbox[6]; // get actual physical height - fb->pitch = mbox[33]; // get number of bytes per line - fb->isrgb = mbox[24]; // get the actual channel order - fb->fbp = (void *)((unsigned long)mbox[28]); + fb.width = mbox[5]; // get actual physical width + fb.height = mbox[6]; // get actual physical height + fb.pitch = mbox[33]; // get number of bytes per line + fb.isrgb = mbox[24]; // get the actual channel order + fb.fbp = (void *)((unsigned long)mbox[28]); } else { puts("Unable to set framebuffer!\r\n"); return 0; } - return fb->fbp; + return fb.fbp; +} + +struct fbst * fb_get(){ + return &fb; +} + +void fb_print(int x, int y, char *s) +{ + // get our font + psf_t *font = (psf_t *)&_binary_font_psf_start; + // draw next character if it's not zero + while (*s) { + // get the offset of the glyph. Need to adjust this to support unicode table + unsigned char *glyph = + (unsigned char *)&_binary_font_psf_start + font->headersize + + (*((unsigned char *)s) < font->numglyph ? *s : 0) * font->bytesperglyph; + // calculate the offset on screen + int offs = (y * fb.pitch) + (x * 4); + // variables + int line, mask, bytesperline = (font->width + 7) / 8; + // handle carrige return + if (*s == '\r') { + x = 0; + } else + // new line + if (*s == '\n') { + x = 0; + y += font->height; + } else { + // display a character + for (unsigned int j = 0; j < font->height; j++) { + // display one row + line = offs; + mask = 1 << (font->width - 1); + for (unsigned int i = 0; i < font->width; i++) { + // if bit set, we use white color, otherwise black + *((unsigned int *)(fb.fbp + line)) = ((int)*glyph) & mask ? 0xFFFFFF : 0; + mask >>= 1; + line += 4; + } + // adjust to next line + glyph += bytesperline; + offs += fb.pitch; + } + x += (font->width + 1); + } + // next character + s++; + } } diff --git a/fb.h b/fb.h index 27216c8..a04a65b 100644 --- a/fb.h +++ b/fb.h @@ -8,4 +8,6 @@ struct fbst { unsigned int isrgb; }; -unsigned char *init_fb(struct fbst *fb); +unsigned char *fb_init(); +struct fbst * fb_get(); +void fb_print(int x, int y, char *s); diff --git a/font.psf b/font.psf new file mode 100644 index 0000000..3e67693 Binary files /dev/null and b/font.psf differ diff --git a/hello.c b/hello.c index acfe3a9..c00efa0 100644 --- a/hello.c +++ b/hello.c @@ -3,11 +3,13 @@ #include "uart.h" #include "utils.h" -struct fbst fb; int kernelmain(void) { - init_uart(); - if (init_fb(&fb) == 0) { + struct fbst *fb; + unsigned char *ptr; + + uart_init(); + if (fb_init() == 0) { puts("Fail to init framebuffer"); } mbox[0] = 8 * 4; @@ -32,10 +34,11 @@ int kernelmain(void) printclock(); - unsigned char *ptr = fb.fbp; + fb = fb_get(); + ptr = fb->fbp; - for (unsigned int y = 0; y < fb.height; y++) { - for (unsigned int x = 0; x < fb.width; x++) { + for (unsigned int y = 0; y < fb->height; y++) { + for (unsigned int x = 0; x < fb->width; x++) { if (y % 60 == 0) *((unsigned int *)ptr) = 0x00FF0000; else if (y % 40 == 0) @@ -47,5 +50,7 @@ int kernelmain(void) ptr += 4; } } + + fb_print(0, 0, "Hello Dude\n"); return 0; } diff --git a/uart.c b/uart.c index 794dc5b..4df3466 100644 --- a/uart.c +++ b/uart.c @@ -4,7 +4,7 @@ #include "gpio.h" -void init_uart(void ) +void uart_init(void ) { //Active waiting while(UART0_FR & (1<<3)){} diff --git a/uart.h b/uart.h index 2fa910e..c6bbf1e 100644 --- a/uart.h +++ b/uart.h @@ -11,6 +11,6 @@ #define UART0_IMSC (*(volatile unsigned *)(UART0_BASE + 0x38)) #define UART0_ICR (*(volatile unsigned *)(UART0_BASE + 0x44)) -void init_uart(void); +void uart_init(void); void putc(char c); void puts(const char *s);