Skip to content

Latest commit

 

History

History
175 lines (132 loc) · 5 KB

File metadata and controls

175 lines (132 loc) · 5 KB

Code: part of Bootloader.asm, ImageMaker.c, and root directory Makefile

;; first part of Bootloader.asm
;; there is KERNEL32SECTORCOUNT constant after TOTALSECTORCOUNT
;; This new constant are accessed by 01.Kernel32/Main.c, so it can
;; copy the 64 bit kernel area to 0x200000(2MB)
;; Bootloader still load the whole image file to 0x10000 and
;; Main.c copies the 64 bit part in memory to 0x200000


; macro:
;  FLOPPY144 : read sectors up to 18 instead of 36

[ORG 0x00]
[BITS 16]

SECTION .text

; initialize code segment before running code
jmp 0x07C0:START

; env for MINT64OS
; TOTALSECTORCOUNT and KERNEL32SECTOR will be modified by ImageMaker
; program in Utility directory.
; When you read the code, just assume that TOTALSECTORCOUNT is total number of
; sectors of overall image except bootloader part
; and KERNEL32SECTOR is the number of sectors of Kernel32 
TOTALSECTORCOUNT: dw 0 
KERNEL32SECTORCOUNT: dw 0

; code section
START:
/* ImageMaker program concatenate Bootloader.bin. Kernel32.bin, and
 * Kernel64.bin to make Disk.img in a way that you do not have to change
 * TOTALSECTORCOUNT and KERNEL32SECTORCOUNT part of BootLoader.asm manually.
 * Also, This program aligns Bootloader.bin and Kernel32.bin into multiply
 * of 512 so the image works on QEMU without problem.
 * Old QEMU fails to load floppy image that is not multiply of 512.
 * The reason that I made this program is that I do not want to change
 * TOTALSECTORCOUNT in BootLoader.asm manually every time I add more C code.
 * Actually, I cannot expect how many bytes the c code will occupy in Disk.img
 * before compiling.
*/

    // more code before...

    // Section 3
    // add Kernel64.bin to Disk.img

    // copy Kernel64.bin to Disk.img
    // iSourceSize is size of Kernel64.bin
    if ((iSourceFd = open(argv[3], O_RDONLY)) == -1) {
    	fprintf(stderr, "[ERROR] %s open fail\n", argv[3]);
    	exit(-1);
    }

    // copy Kernel64.bin to Disk.img
    // ISourceSize is size of Kernel64.bin
    iSourceSize = ConcatenateFile(iSourceFd, iTargetFd);
    close(iSourceFd);

    // add padding
    // iKernel64SectorCount is number of sectors of
    // (size of Kernel64.bin + padding)
    iKernel64SectorCount = AdjustInSectorSize(iTargetFd, iSourceSize);
    printf("[INFO] %s size = [%d] and sector count = [%d]\n",
    		argv[3], iSourceSize, iKernel32SectorCount);


    // more code after...
}

// modify TOTALSECTORCOUNT part of Bootloader.asm so bootloader can
// load image to the memory
// iTargetFd: descriptor of target file
// iTotalKernelSectorCount: number of sectors to load to the memory
// iKernel32SectorCount: number of sectors of Kernel32.bin
void WriteKernelInformation(
    int iTargetFd,
    int iTotalKernelSectorCount,
    int iKernel32SectorCount
) {
    unsigned short usData;
    long lPosition;

    lPosition = lseek(iTargetFd, (off_t) 5, SEEK_SET);

    if (lPosition == -1) {
    	fprintf(stderr, "lseek fail. Return value = %ld, errno = %d, %d\n",
    			lPosition, errno, SEEK_SET);
    	exit(-1);
    }

    usData = (unsigned short) iTotalKernelSectorCount;
    write(iTargetFd, &usData, 2);
    printf("[INFO] Total sector count except boot loader [%d]\n",
    		iTotalKernelSectorCount);

    // file descriptor position pointer is incremented by 2
    // automatically. No need to call lseek again
    usData = (unsigned short) iKernel32SectorCount;
    write(iTargetFd, &usData, 2);
    printf("[INFO] Total sector count of protected mode kernel [%d]\n",
    		iKernel32SectorCount);
}
# Makefile in root directory of Ch10
# Because 02.Kernel64 directory is created, I show modified part of Makefile

.PHONY: all clean run

all: Utility BootLoader Kernel32 Kernel64 Disk.img

Kernel64: 
	@echo
	@echo ============== Build 64bit Kernel ==============
	@echo 

	make -C 02.Kernel64
	
	@echo ============== Build Complete ==============
	@echo	


Disk.img: 00.BootLoader/BootLoader.bin 01.Kernel32/Kernel32.bin 02.Kernel64/Kernel64.bin
	@echo
	@echo ============== Disk Image Build Start ==============
	@echo
	
	04.Utility/01.ImageMaker/ImageMaker $^
	
	@echo
	@echo ============== All Build Complete ==============
	@echo
	
clean:
	make -C 00.BootLoader clean
	make -C 01.Kernel32 clean
	make -C 02.Kernel64 clean
	make -C 04.Utility clean
	rm -f Disk.img

Explanation

Note

Bootloader.asm

  1. There is KERNEL32SECTORCOUNT constant after TOTALSECTORCOUNT. This new constant are accessed by 01.Kernel32/Main.c, so it can copy the 64 bit kernel area to 0x200000(2MB).

  2. Because BootLoader.asm is not input of linker, so you cannot access the constant by name. Instead, you'll see that Main.c directly get the value by directly accessing memory address.

  3. Bootloader still load the whole image file to 0x10000 and Main.c copies the 64 bit part in memory to 0x200000

ImageMaker.c

  1. concatenate Kernel64.bin to Disk.img and align

  2. Change in WriteKernelInformation definition

    • Because Main.c utilizes KERNEL32SECTORCOUNT constant, ImageMaker modified the value to the number of sectors of Kernel32.bin