Commit 9b79673d authored by Jonas Termansen's avatar Jonas Termansen

Initial version of Sortix.

parents
ifndef CPU
CPU=x86
endif
REMOTE=192.168.2.6
REMOTEUSER=sortie
REMOTECOPYDIR:=/home/$(REMOTEUSER)/Desktop/MaxsiOS
MODULES=libmaxsi hello sortix
VERSION=0.4
DEBNAME:=sortix_$(VERSION)_$(CPU)
DEBSRCNAME:=sortix_$(VERSION)
DEBDIR:=builds/$(DEBNAME)
DEBSRCDIR:=builds/$(DEBSRCNAME)-src
DEBFILE:=builds/$(DEBNAME).deb
PACKAGENAME:=sortix
ISODIR:=builds/$(DEBNAME)-iso
ISOFILE:=builds/$(DEBNAME).iso
JSNAME:=jssortix_$(VERSION)_$(CPU).bin
all:
(for D in $(MODULES); do $(MAKE) all $(MFLAGS) --directory $$D; done)
clean:
(for D in $(MODULES); do $(MAKE) clean $(MFLAGS) --directory $$D; done)
distclean: clean cleanbuilds
cleanbuilds:
rm -rf builds/
rm -f sortix.iso
everything: all deb iso jssortix
# Local machine
install: all
cp sortix/sortix.bin /boot
cp debsrc/etc/grub.d/42_sortix /etc/grub.d/42_sortix
chmod +x /etc/grub.d/42_sortix
update-grub
uninstall:
rm -f /boot/sortix.bin
rm -f /etc/grub.d/42_sortix
update-grub
# Remote machine
install-remote: all
scp -r ./ $(REMOTE):$(REMOTECOPYDIR)
scp sortix/sortix.bin root@$(REMOTE):/boot
ssh root@$(REMOTE) "init 6"
uninstall-remote:
ssh root@$(REMOTE) "rm /boot/sortix.bin"
# Packaging
deb: debfile debsource
debfile: all
rm -rf $(DEBDIR)
mkdir -p $(DEBDIR)
cp -r debsrc/. $(DEBDIR)
mkdir -p $(DEBDIR)/boot
cp sortix/sortix.bin $(DEBDIR)/boot
cat debsrc/DEBIAN/control | \
sed "s/SORTIX_PACKAGE_NAME/$(PACKAGENAME)/g" | \
sed "s/SORTIX_VERSION/$(VERSION)/g" | \
sed "s/SORTIX_ARCH/all/g" | \
cat > $(DEBDIR)/DEBIAN/control
dpkg --build $(DEBDIR) $(DEBFILE)
rm -rf $(DEBDIR)/DEBIAN
(cd builds/$(DEBNAME) && tar cfzv ../$(DEBNAME).tar.gz `ls`)
rm -rf $(DEBDIR)
debsource: all
rm -rf $(DEBSRCDIR)
mkdir -p $(DEBSRCDIR)
for D in `ls | grep -v builds`; do cp -r $$D $(DEBSRCDIR); done
(cd $(DEBSRCDIR) && make distclean)
(cd builds && tar cfzv $(DEBSRCNAME)-src.tar.gz $(DEBSRCNAME)-src)
rm -rf $(DEBSRCDIR)
jssortix: all
mkdir -p builds
$(MAKE) jssortix $(MFLAGS) --directory sortix
cp sortix/jssortix.bin builds/$(JSNAME)
# Bootable images
iso: all debsource
rm -rf $(ISODIR)
mkdir -p builds
mkdir -p $(ISODIR)
cp -r isosrc/. $(ISODIR)
cp sortix/sortix.bin $(ISODIR)/boot
cp hello/hello $(ISODIR)/boot/sortix.initrd
cp builds/$(DEBSRCNAME)-src.tar.gz $(ISODIR)
grub-mkrescue -o $(ISOFILE) $(ISODIR)
rm -rf $(ISODIR)
sortix.iso: iso
cp $(ISOFILE) sortix.iso
# Virtualization
run-virtualbox: sortix.iso
virtualbox --startvm sortix
run-virtualbox-debug: sortix.iso
virtualbox --debug --start-running --startvm sortix
Package: SORTIX_PACKAGE_NAME
Version: SORTIX_VERSION
Section: kernel
Priority: optional
Architecture: SORTIX_ARCH
Essential: no
Recommends: grub2, xorriso
Provides: sortix
Maintainer: Jonas Termansen [sortie@maxsi.org]
Description: Sortix is a small hobby kernel developed for the heck of it.
#!/bin/sh
set -e
update-grub
#!/bin/sh
set -e
if [ "$1" != "upgrade" ]; then update-grub; fi
#!/bin/sh
if [ -f /boot/sortix.bin ]; then
echo "Found Sortix kernel: /boot/sortix" >&2
cat << EOF
menuentry "Sortix" {
multiboot /boot/sortix.bin
}
EOF
fi
# This is a bit bothersome design, but it should serve well enough as a simple
# cross-compiler for the Sortix operating system.
ifndef CPU
CPU=x86
endif
ifeq ($(CPU),x86)
X86FAMILY=1
CPUDEFINES=-DPLATFORM_X86
CPUFLAGS=-m32
CPULDFLAGS=-melf_i386
endif
ifeq ($(CPU),x64)
X86FAMILY=1
CPUDEFINES=-DPLATFORM_X64
CPUFLAGS=-m64
CPULDFLAGS=-melf_x86_64
endif
LIBMAXSIROOT=../libmaxsi
INCLUDES=-I $(LIBMAXSIROOT)/c/h/ -I ../
CPPFLAGS=$(CPUDEFINES)
LD=ld
LDFLAGS=$(CPULDFLAGS) -Ttext 400000 $(LIBMAXSIROOT)/start.o
CC=gcc
CFLAGS=$(CPUFLAGS) -nostdinc -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-stack-protector $(INCLUDES)
CXX=g++
CXXFLAGS=$(CPUFLAGS) -nostdinc -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector $(INCLUDES)
LIBC=$(LIBMAXSIROOT)/libc.a
all: hello
hello: hello.o
$(LD) $(LDFLAGS) hello.o -o hello.tmp $(LIBC)
objcopy -O binary hello.tmp hello
hello.o: hello.c
$(CC) $(CPPFLAGS) $(CFLAGS) -O2 -c hello.c -o hello.o
clean:
rm -f hello.tmp hello.o hello
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("\e[m\e[0J");
printf("OH MY GOD! Sortix can load programs!\n");
return 0;
}
insmod part_msdos
insmod ext2
insmod png
if loadfont /boot/grub/fonts/unicode.pf2 ; then
set gfxmode=800x600
insmod vbe
insmod vga
insmod gfxterm
fi
terminal_output gfxterm
if background_image /boot/grub/sortix.png ; then
set color_normal=white/black
set color_highlight=white/light-gray
else
set menu_color_normal=white/black
set menu_color_highlight=white/light-gray
fi
set timeout=10
set default="0"
menuentry "Sortix" {
multiboot /boot/sortix.bin
module /boot/sortix.initrd
}
ifndef CPU
CPU=x86
endif
ifeq ($(CPU),x86)
CPUDEFINES=-DPLATFORM_X86
CPUFLAGS=-m32
CPULDFLAGS=-melf_i386
CPUASFLAGS=-32
CPUNASMFLAGS=-felf32
endif
ifeq ($(CPU),x64)
CPU=x64
CPUDEFINES=-DPLATFORM_X64
CPUFLAGS=-fPIC -m64
CPULDFLAGS=-melf_x86_64
CPUASFLAGS=-64
CPUNASMFLAGS=-felf64
endif
DEFINES=-DLIBMAXSI_LIBRARY -DSORTIX $(CPUDEFINES)
FLAGSRELEASE=-O2
FLAGSDEBUG=-O2
FLAGS=$(CPUFLAGS) -std=gnu++0x -Wall -Wextra -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-stack-protector -nostdinc $(FLAGSRELEASE) $(DEFINES)
LDFLAGS=$(CPULDFLAGS)
ASFLAGS=$(CPUASFLAGS)
NASMFLAGS=$(CPUNASMFLAGS)
COBJS=c/file.o
CHEADERS=\
c/h/unistd.h \
c/h/stdlib.h \
c/h/wchar.h \
c/h/stddef.h \
c/h/fcntl.h \
c/h/stdarg.h \
c/h/wctype.h \
c/h/features.h \
c/h/string.h \
c/h/sys/stat.h \
c/h/sys/types.h \
c/h/stdio.h
COMMONOBJS=c++.o thread.o io.o memory.o string.o error.o format.o
SORTIXOBJS:=$(addprefix sortix/,$(COMMONOBJS))
LIBMAXSIOBJS:=$(COMMONOBJS)
HEADERS=error.h io.h memory.h platform.h string.h syscall.h thread.h types.h format.h
OBJS:=$(LIBMAXSIOBJS)
BINS:=libmaxsi.so
ifndef LIBMAXSI_NO_STATIC
BINS:=$(BINS) libmaxsi.a
endif
ifndef LIBMAXSI_NO_SORTIX
BINS:=$(BINS) libmaxsi-sortix.a start.o
endif
ifndef LIBMAXSI_NO_LIBC
OBJS:=$(OBJS) $(COBJS)
BINS:=$(BINS) libc.so
ifndef LIBMAXSI_NO_STATIC
BINS:=$(BINS) libc.a
endif
HEADERS:=$(HEADERS) $(CHEADERS)
else
DEFINES:=$(DEFINES) -DLIBMAXSI_NO_LIBC
endif
CFLAGS:=$(FLAGS) -std=c99 -Ic/h -I..
CXXFLAGS:=$(FLAGS) -nostdinc++ -fno-rtti -I.. -Ic/h
SORTIXFLAGS:=$(CXXFLAGS) -DSORTIX_KERNEL -I.. -I../..
all: $(BINS)
libmaxsi.a: $(OBJS)
ar rcs libmaxsi.a $(OBJS)
libmaxsi.so: $(OBJS)
ld $(LDFLAGS) -shared -o $@ $(OBJS)
libmaxsi-sortix.a: $(SORTIXOBJS)
ar rcs libmaxsi-sortix.a $(SORTIXOBJS)
libc.a: libmaxsi.a
ln -sf $< $@
libc.so: libmaxsi.so
ln -sf $< $@
# libmaxsi
*.cpp: $(HEADERS)
%.o: %.cpp
g++ -c $< -o $@ $(CXXFLAGS)
%.h: hsrc/%.h
echo "/* WARNING: This header is generated - edits will be lost! */" > $@
mxmpp -I decl $< >> $@
%.o: %.s
as $(ASFLAGS) $< -o $@
%.o: %.asm
nasm $(CPUNASMFLAGS) $< -o $@
# libc
c/*.c: $(CHEADERS)
c/%.o: c/%.c
gcc -c $< -o $@ $(CFLAGS)
c/h/%.h: c/hsrc/%.h
echo "/* WARNING: This header is generated - edits will be lost! */" > $@
mxmpp -I decl -I c/decl $< >> $@
# libmaxsi-sortix
sortix/*.cpp: $(HEADERS)
sortix/%.o: %.cpp $(HEADERS)
g++ -c $< -o $@ $(SORTIXFLAGS)
sortix/%.o: sortix/%.cpp
g++ -c $< -o $@ $(SORTIXFLAGS)
clean:
rm -f *.o sortix/*.o c/*.o *.a *.so $(CHEADERS) $(HEADERS)
/******************************************************************************
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
This file is part of LibMaxsi.
LibMaxsi is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.
You should have received a copy of the GNU Lesser General Public License
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
c++.cpp
Implements required C++ stuff for use in the Sortix kernel.
******************************************************************************/
#include "platform.h"
extern "C" void __cxa_pure_virtual()
{
// This shouldn't happen. TODO: Possibly crash the kernel here.
}
#ifdef PLATFORM_X86
// TODO: These two stubs are buggy!
// Divides two 64-bit integers in O(logN). I think.
extern "C" uint64_t __udivdi3(uint64_t A, uint64_t B)
{
uint64_t ACC = 0;
uint64_t R = 0;
uint64_t PWR = 1;
uint64_t EXP = B;
while ( EXP <= A - ACC )
{
R += PWR;
ACC += EXP;
if ( 2 * EXP <= A - ACC )
{
PWR++;
EXP *= 2;
}
else if ( A - ACC < B )
{
break;
}
else
{
while ( A - ACC < EXP )
{
PWR--;
EXP /= 2;
}
}
}
return R;
}
// Mods two 64-bit integers in O(logN). I think.
extern "C" uint64_t __umoddi3(uint64_t A, uint64_t B)
{
uint64_t ACC = 0;
uint64_t R = 0;
uint64_t PWR = 1;
uint64_t EXP = B;
while ( EXP <= A - ACC )
{
R += PWR;
ACC += EXP;
if ( 2 * EXP <= A - ACC )
{
PWR++;
EXP *= 2;
}
else if ( A - ACC < B )
{
break;
}
else
{
while ( A - ACC < EXP )
{
PWR--;
EXP /= 2;
}
}
}
return A - ACC;
}
#endif
#ifndef _FILE_DECL
#define _FILE_DECL
struct _IO_FILE;
typedef struct _IO_FILE FILE;
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1 /* Seek from current position. */
#endif
#ifndef SEEK_SET
#define SEEK_SET 2 /* Seek from end of file. */
#endif
#ifndef SEEK_SET
#define SEEK_SET 0 /* Seek from beginning of file. */
#endif
#ifndef WEOF
#define WEOF (-1)
#endif
#ifndef _USECONDS_T_DECL
#define _USECONDS_T_DECL
typedef __useconds_t useconds_t;
#endif
#ifndef _WCTRANS_T_DECL
#define _WCTRANS_T_DECL
typedef __wctrans_t wctrans_t;
#endif
#ifndef _WCTYPE_T_DECL
#define _WCTYPE_T_DECL
typedef __wctype_t wctype_t;
#endif
/******************************************************************************
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
This file is part of LibMaxsi.
LibMaxsi is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.
You should have received a copy of the GNU Lesser General Public License
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
file.c
Implements every related to the FILE structure. This API is not compatible
enough with LibMaxsi's design goals, so it is implemented as a layer upon
the C functions in LibMaxsi.
******************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <fcntl.h>
#if 0
// TODO: Make a real errno system!
volatile int errno;
#define EINVAL 1
typedef struct
{
off_t pos;
mbstate_t state;
} _fpos_t;
struct _IO_FILE
{
int fd;
_fpos_t pos;
};
// TODO: Actually implement these stubs.
char* fgets(char* restrict s, int n, FILE* restrict stream)
{
return NULL;
}
FILE* fdopen(int fildes, const char* mode)
{
return NULL;
}
FILE *fmemopen(void* restrict buf, size_t size, const char* restrict mode)
{
return NULL;
}
FILE* fopen(const char* restrict filename, const char* restrict mode)
{
int len;
if ( mode[0] == '\0' ) { errno = EINVAL; return NULL; } else
if ( mode[1] == '\1' ) { len = 1; } else
if ( mode[2] == '\0' ) { len = 2; }
if ( mode[3] == '\0' ) { len = 3; } else { errno = EINVAL; return NULL; }
int oflags;
if ( len == 1 || (len == 2 && mode[1] == 'b') )
{
switch ( mode[0] )
{
case 'r': oflags = O_RDONLY; break;
case 'w': oflags = O_WRONLY | O_TRUNC | O_CREAT; break;
case 'a': oflags = O_WRONLY | O_APPEND | O_CREAT; break;
default: errno = EINVAL; return NULL;
}
}
else if ( (len == 2 && mode[1] == '+') || (len == 3 && mode[1] == '+' && mode[1] == 'b') || (len == 3 && mode[1] == 'b' && mode[1] == '+') )
{
switch ( mode[0] )
{
case 'r': oflags = O_RDWR; break;
case 'w': oflags = O_RDWR | O_TRUNC | O_CREAT; break;
case 'a': oflags = O_RDWR | O_APPEND | O_CREAT; break;
default: errno = EINVAL; return NULL;
}
}
else { errno = EINVAL; return NULL; }
// TODO: Does anything else modify this mask?
// TODO: POSIX says this should be "S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH",
// but Linux applies this in a simple test case!
mode_t perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
FILE* file = malloc(sizeof(FILE));
if ( file == NULL ) { return NULL; }
int fd = open(filename, oflags, perms);
if ( fd < 0 ) { free(file); return NULL; }
file->fd = fd;
// TODO: set other stuff here!
return file;
}
FILE* freopen(const char* restrict filename, const char *restrict mode, FILE* restrict stream)
{
return NULL;
}
FILE* popen(const char* command, const char* mode)
{
return NULL;
}
FILE* tmpfile(void)
{
return NULL;
}
int fclose(FILE* stream)
{
return -1;
}
int feof(FILE* stream)
{
return -1;
}
int ferror(FILE* stream)
{
return -1;
}
int fflush(FILE* stream)
{
return -1;
}
int fgetc(FILE* stream)
{
return -1;
}
int fgetpos(FILE* restrict stream, fpos_t* restrict pos)
{
return -1;
}
int fileno(FILE* stream)
{
return -1;
}
int fprintf(FILE* restrict stream, const char* restrict format, ...)
{
return -1;
}
int fputc(int c, FILE* stream)
{
return -1;
}
int fputs(const char* restrict s, FILE* restrict stream)
{
return -1;
}
int fscanf(FILE* restrict stream, const char* restrict format, ... )