Initial commit

This commit is contained in:
pjht 2024-03-19 09:23:21 -05:00
commit 6819e313c8
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
8 changed files with 488 additions and 0 deletions

7
Tupfile Normal file
View File

@ -0,0 +1,7 @@
.gitignore
LDFLAGS = -z max-page-size=4096 --orphan-handling=error -T proglink.ld
ASFLAGS = -m68010 -spaces -Felf -ldots -align -quiet -x -nowarn=62
: foreach *.68k | ../<include> |> vasmm68k_mot $(ASFLAGS) -I../sysroot/usr/include -o %o %f |> %B.o
: *.o | proglink.ld ../<libstd> |> m68k-elf-ld $(LDFLAGS) -o %o %f '%<libstd>' |> init

51
cards.68k Normal file
View File

@ -0,0 +1,51 @@
include syscalls.i
section .text,text
public cards_init
cards_init:
move.l #$ffff0000, d0
move.l #16, d1
move.l #$2, d2
jsr syscall_vmem_map_free_to
move.l a0, (io_space_start)
rts
; Finds the first card with the type in d0.b, and returns it's IO base address in a0, or 0 if not found
; Clobbers d1
public find_first_card
find_first_card:
move.l io_space_start, a0 ; a0 holds the address of the current card
ffc_loop:
lea ($100,a0), a0 ; Move to the next card
move.w ($fe,a0), d1 ; Load the type of the card into d1
beq.b ffc_done ; If the type is 0 (empty slot), we have scanned all cards, so exit the loop
cmp.b d0, d1 ; If the card is the type we want, return with the address in a0
beq.b ffc_done
bra.b ffc_loop ; Loop back and check the next card
ffc_done:
rts
get_all_cards:
; Gets the indexes of the cards with the specified type
; a0 is a pointer to the buffer to store the results in
; d0 is the length of the buffer in 4 byte units
; d1 is the type of card to find
move.l io_space_start, a1 ; a0 holds the address of the current card
gac_loop:
lea ($100,a1), a1 ; Move to the next card
move.w ($fe,a1), d2 ; Load the type of the card into d1
cmp.b d1, d2 ; Check whether the type of the current card is the type we want
bne.b gac_next ; Skip the card if it is not
move.l a1, (a0) ; Put the card base into the buffer
lea ($4,a0), a0 ; Move to the next buffer location
subq.w #1, d0 ; Decement the count of available buffer locations
gac_next:
cmpa.l #$ffff00, a1 ; Check if we have gone through all the cards
beq.b gac_done ; If so, return
cmpi.b #0, d0 ; Check if we have filled the buffer
beq.b gac_done ; If so, returm
bra.b gac_loop
gac_done:
rts
section .bss,bss
io_space_start: ds.l 1

7
cards.i Normal file
View File

@ -0,0 +1,7 @@
ifnd CARDS_I
CARDS_I equ 1
xref cards_init
; Finds the first card with the type in d0.b, and returns it's IO base address in a0, or 0 if not found
; Clobbers d1
xref find_first_card
endif

29
init.68k Normal file
View File

@ -0,0 +1,29 @@
include cards.i
include initrd.i
include syscalls.i
section .text,text
public _start
_start:
move.l #tmp_stack_top, a7
; set up a permanent stack
move.l #2, d0
move.l #$2, d1
jsr syscall_vmem_map_free
adda.l #(2*4096), a0
move.l a0, a7
move.l #msg, a0
jsr syscall_println
jsr cards_init
jsr initrd_init
move.l #init_name, a0
jsr initrd_find_file
dbg:
jsr syscall_exit
section .data,data
msg: dc.b "Hello from init",0
init_name: dc.b "init.elf",0
section .bss,bss
tmp_stack: ds.b 32
tmp_stack_top:

155
initrd.68k Normal file
View File

@ -0,0 +1,155 @@
STORAGE_SEC equ $0
STORAGE_CNT equ $4
STORAGE_CMD equ $8
STORAGE_DMADR equ $C
include cards.i
include memory.i
include string.i
section .text,text
; Initialize the initrd reader
public initrd_init
initrd_init:
move.w #$4, d0 ; Get the pointer to the MMU card
jsr find_first_card
move.l a0, storage_card_base
rts
; Get the start byte for a specific file in the initrd
; Pointer to name in a0
; Number returned in d0, or 0 if not found
public initrd_find_file
initrd_find_file:
movem.l d2/a2, -(a7)
move.l a0, a2
move.l #512, d0
jsr malloc
move.l a0, a1
move.l #1, d0
iff_loop:
movem.l d0/a0/a1, -(a7)
move.l storage_card_base, a0
move.l #1, d1
bsr.b read_sectors
movem.l (a7)+, d0/a0/a1
move.l (a1), d2
bne.b .1
move.l #0, d0
bra.b iff_done
.1:
; File name at (12, a1)
; Passed in name at a2
movem.l d0/a0/a1, -(a7)
move.l a2, a0
adda.l #12, a1
jsr strcmp
movem.l (a7)+, d0/a0/a1
bne.b .2
addi.l #1, d0
movem.l (a7)+, d2/a2
lsl.l #8, d0
lsl.l #1, d0
rts
.2:
addi.l #1, d0
move.l (4,a1), d2
add.l d2, d0
bra.b iff_loop
iff_done:
movem.l (a7)+, d2/a2
rts
; Reads bytes of a file from the initrd
; Start byte of file in d0
; Offset in d1
; Length in d2
; Buffer in a0
public initrd_read_bytes
initrd_read_bytes:
add.l d1, d0
move.l d2, d1
move.l a0, a1
move.l storage_card_base, a0
bra.b read_bytes
; Reads sectors from a storage card
; Card base in a0
; Destination in a1
; Start sector in d0.l
; Sector count in d1.l
read_sectors:
cmpi.l #0, d1
beq.b read_sectors_done
move.l d0, (STORAGE_SEC,a0) ; Set the sector number
move.l d1, (STORAGE_CNT,a0) ; Set the sector count
move.l a1, (STORAGE_DMADR,a0) ; Set the destination address
move.w #$1, (STORAGE_CMD,a0) ; Issue a DMA read command
read_sectors_done:
rts
; Reads bytes off a storage card
; Card base in a0
; Destination in a1
; Start byte in d0.l
; Byte count in d1.l
read_bytes:
movem.l d2-d5/a2/a3,-(a7) ; Save callee preserved registers
move.l d0, d4 ; Save start byte in d4
move.l d1, d5 ; Save byte count in d5
move.l a1, a3 ; Save destination in a6
lsr.l #8, d0 ; Divide start byte by 512 to compute starting sector
lsr.l #1, d0
move.l d0, d3 ; Save the starting sector in d3
move.l #1, d1 ; Read the starting sector into the sector buffer
move.l #sec_buf, a1
bsr.b read_sectors
move.l a3, a2 ; Load the destination into a2
move.l d4, d0 ; Load the start byte into d0
andi.l #$1FF, d0 ; Modulus start byte by 512 to compute sector data offset
adda.l d0, a1 ; Add the offset to the start of the sector buffer
move.l #$200, d1 ; Compute the number of bytes to transfer by subtracting the offset from 512
sub.l d0, d1
cmp d5, d1 ; Compare the number of bytes to transfer with the byte count
ble.b count_ok ; If it was less than the byte count, do not adjust the bytes to transfer
move.l d5, d1 ; Otherwise, cap the transfer count to the total byte count
count_ok:
move.l d1, d4 ; Save the number of bytes in d4
subi.l #1, d1 ; Subtract 1 from the number of bytes to account for the extra loop done by dbra
start_sec_loop: ; Transfer the required bytes from the start sector to the destination buffer
move.b (a1)+, (a2)+
dbra d1, start_sec_loop
move.l d3, d0 ; Load the starting sector into d0
addi #1, d0 ; Compute the start of the middle sectors by adding 1 to the starting sector
move.l d4, d2 ; Load the number of bytes transferred into d2
move.l d5, d1 ; Load the byte count into d1
sub.l d2, d1 ; Compute the number of remaining bytes by subtracting the number of transferred bytes from the byte count
cmpi.l #0, d1 ; If there are no more bytes to read, end early
beq.b read_bytes_done
move.l d1, d4 ; Save the number of remaining bytes in d4
lsr.l #8, d1 ; Divide remaining bytes by 512 to compute the number of middle sectors
lsr.l #1, d1
move.l a2, a1 ; Transfer the sector data to the end of the start sector bytes
bsr.b read_sectors ; Read the middle sectors
move.l d1, d3 ; Save the number of middle sectors in d3
lsl.l #8, d1 ; Multiply the number of middle sectors by 512 to compute the number of bytes transferred
lsl.l #1, d1
sub.l d1, d4 ; Subtract the number of transferred bytes from the number of remaining bytes
cmpi.l #0, d4 ; If there are no more bytes to read, end early
beq.b read_bytes_done
adda.l d1, a2 ; Add the number of bytes transferred to a2
add.l d3, d0 ; Compute the end sector number by adding the start and count of the middle sectors
move.l #1, d1 ; Set the number of sectors to read to 1
move.l #sec_buf, a1 ; Set the read address of the sector to the sector buffer
bsr.w read_sectors ; Read the end sector
move.l d4, d1 ; Load the number of remaining bytes into d1
end_sec_loop: ; Transfer the required bytes from the start sector to the destination buffer
move.b (a1)+, (a2)+
dbra d1, end_sec_loop
read_bytes_done:
movem.l (a7)+, d2-d5/a2/a3 ; Restore callee preserved registers
rts
section .bss,bss
storage_card_base: ds.b 4
sec_buf: ds.b 512

17
initrd.i Normal file
View File

@ -0,0 +1,17 @@
ifnd INITRD_I
INITRD_I equ 1
; Initialize the initrd reader
xref initrd_init
; Get the start byte for a specific file in the initrd
; Pointer to name in a0
; Number returned in d0, or 0 if not found
xref initrd_find_file
; Reads bytes of a file from the initrd
; Start byte of file in d0
; Offset in d1
; Length in d2
; Buffer in a0
xref initrd_read_bytes
endif

0
os.dsk Normal file
View File

222
proglink.ld Normal file
View File

@ -0,0 +1,222 @@
/* Script for -z combreloc */
/* Copyright (C) 2014-2023 Free Software Foundation, Inc.
Copying and distribution of this script, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. */
OUTPUT_FORMAT("elf32-m68k", "elf32-m68k",
"elf32-m68k")
OUTPUT_ARCH(m68k)
ENTRY(_start)
SEARCH_DIR("/usr/m68k-elf/lib");
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x1000)); . = SEGMENT_START("text-segment", 0x1000) + SIZEOF_HEADERS;
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rela.dyn :
{
*(.rela.init)
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.fini)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
*(.rela.ctors)
*(.rela.dtors)
*(.rela.got)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
PROVIDE_HIDDEN (__rela_iplt_start = .);
*(.rela.iplt)
PROVIDE_HIDDEN (__rela_iplt_end = .);
}
.rela.plt :
{
*(.rela.plt)
}
.init :
{
KEEP (*(SORT_NONE(.init)))
} =0x4e714e71
.plt : { *(.plt) }
.iplt : { *(.iplt) }
.text :
{
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(SORT(.text.sorted.*))
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf.em. */
*(.gnu.warning)
} =0x4e714e71
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} =0x4e714e71
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.sframe : ONLY_IF_RO { *(.sframe) *(.sframe.*) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
/* These sections are generated by the Sun/Oracle C++ compiler. */
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.sframe : ONLY_IF_RW { *(.sframe) *(.sframe.*) }
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
/* Thread Local Storage sections */
.tdata :
{
PROVIDE_HIDDEN (__tdata_start = .);
*(.tdata .tdata.* .gnu.linkonce.td.*)
}
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) }
. = DATA_SEGMENT_RELRO_END (0, .);
.got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
_edata = .; PROVIDE (edata = .);
. = .;
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we do not
pad the .data section. */
. = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
. = SEGMENT_START("ldata-segment", .);
. = ALIGN(32 / 8);
_end = .; PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 (INFO) : { *(.comment); LINKER_VERSION; }
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1. */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions. */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2. */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2. */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions. */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3. */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
/* DWARF 5. */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.debug_sup 0 : { *(.debug_sup) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}