#############################################################################
#                  ALMOS-MKH  Makefile for Kernel                           #
#############################################################################

-include ../params-soft.mk
ifeq ($(ARCH_NAME),)
$(error Please define in ARCH_NAME parameter in params-soft.mk!)
endif

#We choose drivers and hal file to be linked with kernel.elf
ifeq ($(ARCH_NAME), tsar_mips32)

  DRIVERS_OBJS = $(HAL_ARCH)/build/drivers/soclib_tty.o  \
                 $(HAL_ARCH)/build/drivers/soclib_bdv.o  \
                 $(HAL_ARCH)/build/drivers/soclib_hba.o  \
                 $(HAL_ARCH)/build/drivers/soclib_mmc.o  \
                 $(HAL_ARCH)/build/drivers/soclib_pic.o  \
                 $(HAL_ARCH)/build/drivers/soclib_nic.o  \
                 $(HAL_ARCH)/build/drivers/soclib_dma.o  \
                 $(HAL_ARCH)/build/drivers/soclib_iob.o

  HAL_OBJS     = $(HAL_ARCH)/build/core/hal_special.o    \
                 $(HAL_ARCH)/build/core/hal_context.o    \
                 $(HAL_ARCH)/build/core/hal_atomic.o     \
                 $(HAL_ARCH)/build/core/hal_remote.o     \
                 $(HAL_ARCH)/build/core/hal_uspace.o     \
                 $(HAL_ARCH)/build/core/hal_irqmask.o    \
                 $(HAL_ARCH)/build/core/hal_gpt.o        \
                 $(HAL_ARCH)/build/core/hal_ppm.o        \
                 $(HAL_ARCH)/build/core/hal_vmm.o        \
                 $(HAL_ARCH)/build/core/hal_kentry.o     \
                 $(HAL_ARCH)/build/core/hal_switch.o     \
                 $(HAL_ARCH)/build/core/hal_syscall.o    \
                 $(HAL_ARCH)/build/core/hal_exception.o  \
                 $(HAL_ARCH)/build/core/hal_interrupt.o  \
                 $(HAL_ARCH)/build/core/hal_drivers.o
endif

ifeq ($(ARCH_NAME), x86_64)

  DRIVERS_OBJS = $(HAL_ARCH)/build/drivers/ioc_ata.o     \
                 $(HAL_ARCH)/build/drivers/pic_apic.o    \
                 $(HAL_ARCH)/build/drivers/txt_rs232.o

  HAL_OBJS     = $(HAL_ARCH)/build/core/hal_boot.o       \
                 $(HAL_ARCH)/build/core/hal_smpboot.o    \
                 $(HAL_ARCH)/build/core/hal_init.o       \
                 $(HAL_ARCH)/build/core/hal_cpu.o        \
                 $(HAL_ARCH)/build/core/hal_kentry.o     \
                 $(HAL_ARCH)/build/core/hal_acpi.o       \
                 $(HAL_ARCH)/build/core/hal_apic.o       \
                 $(HAL_ARCH)/build/core/x86_printf.o     \
                 $(HAL_ARCH)/build/core/hal_drivers.o    \
                 $(HAL_ARCH)/build/core/hal_special.o    \
                 $(HAL_ARCH)/build/core/hal_context.o    \
                 $(HAL_ARCH)/build/core/hal_atomic.o     \
                 $(HAL_ARCH)/build/core/hal_remote.o     \
                 $(HAL_ARCH)/build/core/hal_uspace.o     \
                 $(HAL_ARCH)/build/core/hal_irqmask.o    \
                 $(HAL_ARCH)/build/core/hal_gpt.o        \
                 $(HAL_ARCH)/build/core/hal_ppm.o        \
                 $(HAL_ARCH)/build/core/hal_exception.o  \
                 $(HAL_ARCH)/build/core/hal_interrupt.o  \
                 $(HAL_ARCH)/build/core/hal_syscall.o
endif

LIBGCC = -L$(shell $(CC) -print-libgcc-file-name | sed 's/libgcc.a//') #todo ?

# Rules that don't build target files
# always out-of-date, need to be regenerated everytime they are called
.PHONY: compile			        \
		dirs				    \
		clean				    \
		build/kernel.elf


# Objects to be linked for kernel.elf generation
KERN_OBJS	= build/kern/kernel_init.o     \
              build/kern/printk.o          \
              build/kern/thread.o          \
              build/kern/process.o         \
              build/kern/chdev.o           \
              build/kern/cluster.o         \
              build/kern/scheduler.o       \
              build/kern/core.o            \
              build/kern/dqdt.o            \
              build/kern/do_syscall.o      \
              build/kern/do_interrupt.o    \
              build/kern/rpc.o 

DEV_OBJS    = build/devices/dev_txt.o      \
              build/devices/dev_ioc.o      \
              build/devices/dev_mmc.o      \
              build/devices/dev_nic.o      \
              build/devices/dev_pic.o      \
              build/devices/dev_dma.o      \
              build/devices/dev_fbf.o      \
              build/devices/dev_iob.o

MM_OBJS     = build/mm/ppm.o               \
              build/mm/vmm.o               \
              build/mm/vseg.o              \
              build/mm/page.o              \
              build/mm/kcm.o               \
              build/mm/khm.o               \
              build/mm/mapper.o            \
              build/mm/kmem.o

LIBK_OBJS   = build/libk/grdxt.o           \
              build/libk/bits.o            \
              build/libk/elf.o             \
              build/libk/string.o          \
              build/libk/ctype.o           \
              build/libk/rwlock.o          \
              build/libk/spinlock.o        \
              build/libk/barrier.o         \
              build/libk/remote_barrier.o  \
              build/libk/remote_spinlock.o \
              build/libk/remote_rwlock.o   \
              build/libk/remote_fifo.o     \
              build/libk/remote_mutex.o    \
              build/libk/remote_sem.o      \
              build/libk/remote_condvar.o  \
              build/libk/memcpy.o          \
              build/libk/htab.o            \
              build/libk/xhtab.o

SYS_OBJS_0  = build/syscalls/sys_thread_exit.o     \
              build/syscalls/sys_thread_yield.o    \
              build/syscalls/sys_thread_create.o   \
              build/syscalls/sys_thread_join.o     \
              build/syscalls/sys_thread_detach.o   \
              build/syscalls/sys_thread_cancel.o   \
              build/syscalls/sys_sem.o             \
              build/syscalls/sys_condvar.o         \
              build/syscalls/sys_barrier.o         \
              build/syscalls/sys_mutex.o

SYS_OBJS_1  = build/syscalls/sys_exit.o            \
              build/syscalls/sys_munmap.o          \
              build/syscalls/sys_open.o            \
              build/syscalls/sys_mmap.o            \
              build/syscalls/sys_read.o            \
              build/syscalls/sys_write.o           \
              build/syscalls/sys_lseek.o           \
              build/syscalls/sys_close.o           \
              build/syscalls/sys_unlink.o          \
              build/syscalls/sys_pipe.o

SYS_OBJS_2  = build/syscalls/sys_chdir.o           \
              build/syscalls/sys_mkdir.o           \
              build/syscalls/sys_mkfifo.o          \
              build/syscalls/sys_opendir.o         \
              build/syscalls/sys_readdir.o         \
              build/syscalls/sys_closedir.o        \
              build/syscalls/sys_getcwd.o          \
              build/syscalls/sys_isatty.o          \
              build/syscalls/sys_alarm.o           \
              build/syscalls/sys_rmdir.o

SYS_OBJS_3  = build/syscalls/sys_utls.o            \
              build/syscalls/sys_chmod.o           \
              build/syscalls/sys_signal.o          \
              build/syscalls/sys_timeofday.o       \
              build/syscalls/sys_kill.o            \
              build/syscalls/sys_getpid.o          \
              build/syscalls/sys_fork.o            \
              build/syscalls/sys_exec.o            \
              build/syscalls/sys_stat.o            \
              build/syscalls/sys_wait.o 

SYS_OBJS_4  = build/syscalls/sys_get_config.o      \
              build/syscalls/sys_get_core.o        \
              build/syscalls/sys_get_cycle.o       \
              build/syscalls/sys_display.o         \
              build/syscalls/sys_thread_sleep.o    \
              build/syscalls/sys_thread_wakeup.o   \
              build/syscalls/sys_trace.o           \
              build/syscalls/sys_fg.o              \
              build/syscalls/sys_is_fg.o

VFS_OBJS    = build/fs/vfs.o              \
              build/fs/fatfs.o            \
              build/fs/devfs.o            \
              build/fs/ramfs.o

# List of directories to be searched for included files
# when compiling for kernel.elf generation
KERNEL_INCLUDE = -I.                  \
                 -Ikern             \
                 -Idevices          \
                 -Isyscalls         \
                 -I$(SHARED_INCLUDE)  \
                 -I$(HAL_ARCH)/drivers \
                 -Isyscalls            \
                 -Ilibk                \
                 -Imm                  \
                 -Ifs                  \
                 -I../tools/arch_info  \
                 -I$(HAL)/generic      \
                 -I$(HAL_ARCH)/core    \
                 -I..

# Rule to generate kernel.elf.
compile: dirs                     \
         build/kernel.elf

# Rule to create the build directories.
dirs:
	@mkdir -p build
	@mkdir -p build/kern
	@mkdir -p build/hal
	@mkdir -p build/devices
	@mkdir -p build/mm
	@mkdir -p build/libk
	@mkdir -p build/drivers
	@mkdir -p build/fs
	@mkdir -p build/syscalls


##############################
# rules to compile the drivers and hal
$(HAL_ARCH)/build/%:
	$(MAKE) -C $(HAL_ARCH)

#######################################
# Rules to generate kernel/kern objects
build/kern/%.o:		    kern/%.c                      \
                        kern/%.h                      \
                        kernel_config.h               \
                        $(HAL_ARCH)/core/hal_kernel_types.h
	$(CC) $(KERNEL_INCLUDE) $(CFLAGS) -c -o $@ $<


######################################
# Rules to generate kernel/dev objects
build/devices/%.o:      devices/%.c                   \
                        devices/%.h                   \
                        kernel_config.h               \
                        $(HAL_ARCH)/core/hal_kernel_types.h
	$(CC) $(KERNEL_INCLUDE) $(CFLAGS) -c -o $@ $<

#####################################
# Rules to generate kernel/mm objects
build/mm/%.o:           mm/%.c                        \
                        mm/%.h                        \
                        kernel_config.h               \
                        $(HAL_ARCH)/core/hal_kernel_types.h
	$(CC) $(KERNEL_INCLUDE) $(CFLAGS) -c -o $@ $<

#######################################
# Rules to generate kernel/libk objects
build/libk/%.o:         libk/%.c                      \
                        libk/%.h                      \
                        kernel_config.h               \
                        $(HAL_ARCH)/core/hal_kernel_types.h
	$(CC) $(KERNEL_INCLUDE) $(CFLAGS) -c -o $@ $<

###########################################
# Rules to generate kernel/syscalls objects
build/syscalls/%.o:     syscalls/%.c                  \
                        syscalls/syscalls.h           \
                        kernel_config.h               \
                        $(HAL_ARCH)/core/hal_kernel_types.h
	$(CC) $(KERNEL_INCLUDE) $(CFLAGS) -c -o $@ $<

#######################################
# Rules to generate kernel/fs objects
build/fs/%.o:           fs/%.c                        \
                        fs/%.h                        \
                        kernel_config.h               \
                        $(HAL_ARCH)/core/hal_kernel_types.h
	$(CC) $(KERNEL_INCLUDE) $(CFLAGS) -c -o $@ $<

##############################
# Rule to generate kernel.elf
build/kernel.elf:	    $(KERN_OBJS)                 \
                        $(HAL_OBJS_0)                \
                        $(HAL_OBJS_1)                \
                        $(DEV_OBJS)                  \
                        $(MM_OBJS)                   \
                        $(LIBK_OBJS)                 \
                        $(DRIVERS_OBJS)              \
                        $(VFS_OBJS)                  \
                        $(SYS_OBJS_0)                \
                        $(SYS_OBJS_1)                \
                        $(SYS_OBJS_2)                \
                        $(SYS_OBJS_3)                \
                        $(SYS_OBJS_4)                \
    	                $(HAL_ARCH)/kernel.ld
	$(LD) -o $@ -T $(HAL_ARCH)/kernel.ld $(LIBGCC)         \
          $(KERN_OBJS) $(HAL_OBJS) $(DEV_OBJS) $(MM_OBJS)  \
          $(LIBK_OBJS) $(DRIVERS_OBJS) $(VFS_OBJS)         \
          $(SYS_OBJS_0) $(SYS_OBJS_1) $(SYS_OBJS_2)        \
          $(SYS_OBJS_3) $(SYS_OBJS_4) -lgcc
	$(DU) -D $@ > $@.txt

clean:
	rm -rf build/*
