ウォンツテック

そでやまのーと

リンカスクリプトを以下のようにし、bootmiddleが0x1000(8セクション=8*512byte)あるようにbootacient.SのFD読み込み部分を書き直して解決。
苦肉の策だけどまぁ良しとしよう。
※0x800〜0x1000の0x800バイトが無駄になる。
※kernelを0x1000000などに置き直す場合はこの手法は使えない。

boot.ld

SECTIONS {
        .text ALIGN(0x200) : {
                "boota.o"(.text)
                "bootm.o"(.text)

                . = 0x1000;
                "cstart.o"(.text)
                "kernel.o"(.text)
        }
        .rodata : {}
        .bss ALIGN(0x200) : {}
        .data ALIGN(0x200) : {
                *(EXCLUDE_FILE (*bootm.o) .data)
                . = ALIGN(0x6000);
                "bootm.o"(.data)
        }
}

makefile

makefileも修正

BASEDIR = /home/sode/prog/sodex
SRCDIR  = ${BASEDIR}/src
BIN             = ${BASEDIR}/bin
LIST    = ${BASEDIR}/list
INCLUDE = ${SRCDIR}/include

AS              = /usr/bin/as
CC              = /usr/bin/gcc
LD              = /usr/bin/ld

CFLAGS  = -nostdlib -fno-exceptions -ffreestanding -fno-builtin -Wall
LFLAGS  = -T boot.ld -Map ${LIST}/boot.map --oformat binary

KERNEL  = boot.bin

ACIENT  = boota.o
MIDDLE  = bootm.o

SRC             = cstart.c              \
                  kernel.c              \
                  vga.c

OBJS    = $(SRC:.c=.o)

ASMSRC  = vga_core.S

HEADER  = kernel.h              \
                  vga.h

${KERNEL} : ${ACIENT} ${MIDDLE} ${OBJS} vga_core.o boot.ld
        ${LD} ${LFLAGS} ${ACIENT} ${MIDDLE} ${OBJS} vga_core.o -o $@

${ACIENT} : bootacient.S
        ${AS} bootacient.S -o $@ -a > ${LIST}/boota.lst

${MIDDLE} : bootmiddle.S
        ${AS} bootmiddle.S -o $@ -a > ${LIST}/bootm.lst

vga_core.o : vga_core.S
        ${AS} vga_core.S -o $@ -a > ${LIST}/vga_core.lst

%.o: %.c
        $(CC) -c ${CFLAGS} -I ${INCLUDE} -o $@ $<

表示周りのAPIを書いた。

vga.c

#include "vga.h"

static int screenX = 0;
static int screenY = 0;
static char gColor = 0xf;

void sysPointPrintc(int x, int y, char c)
{
  sysPointColorPrintc(x, y, gColor, c);
}

void sysPrintc(char c)
{
  if (c == '\n') {
        screenX = 0;
        if (screenY + 1 > SCREEN_HEIGHT) {
          sysScreenScrollUp();
        } else
          screenY++;
        return;
  }

  sysPointColorPrintc(screenX, screenY, gColor, c);

  if (screenX + 1 > SCREEN_WIDTH) {
        if (screenY + 1 > SCREEN_HEIGHT) {
          sysScreenScrollUp();
        } else
          screenY++;
  }
  screenX = (screenX + 1)%SCREEN_WIDTH;
}

void sysPrints(char *str)
{
  char *p = str;
  while (*p != '\0') {
        sysPrintc(*p);
        p++;
  }
}

void sysClearScreen()
{
  int x, y;

  for (y=0; y <= SCREEN_HEIGHT; ++y)
        for (x=0; x <= SCREEN_WIDTH; ++x)
          sysPointPrintc(x, y, 0);
}

void sysScreenScrollUp()
{
  int i, j;
  for (i = SCREEN_WIDTH, j=0; i < SCREEN_WIDTH*SCREEN_HEIGHT; ++i, ++j)
        VRAM[2 * j] = VRAM[2 * i];
}

void sysScreenPointSet(int x, int y)
{
  screenX = x;
  screenY = y;
}

void sysScreenSetColor(char color)
{
  gColor = color;
}

void sysScreenInitial()
{
  sysClearScreen();
  sysPrints("------------------------------------------------------------\n");
  sysPrints("     This is Sodex Kernel.                                  \n");
  sysPrints("      The kernel is starting.                               \n");
  sysPrints("      Now, we're going to implement the A20 and VGA         \n");
  sysPrints("------------------------------------------------------------\n");
}

vga_core.S

#include "vga.h"

VRAM_ADDRESS    = 0xb8000

.code32
.text
.global sysPointColorPrintc

/* void sysPointColorPrintc(int x, int y, char color, char c)
 * In this code, x is ebx, y is eax, color is dh, c is dl
 */
sysPointColorPrintc:
                pushl   %ebp
                movl    %esp, %ebp
                movl    0xc(%ebp), %eax
                movw    $80, %cx
                mulw    %cx                             # eax = y * 80
                movw    $2, %cx
                mulw    %cx                             # eax = y * 80 * 2

                movl    0x8(%ebp), %ebx
                addl    %ebx, %eax
                addl    %ebx, %eax
                addl    $VRAM_ADDRESS, %eax
                movb    0x14(%ebp), %dl # set color
                movb    0x10(%ebp), %dh # set char
                movw    %dx, (%eax)

                popl    %ebp
                ret