;; 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
-
There is
KERNEL32SECTORCOUNT
constant afterTOTALSECTORCOUNT
. This new constant are accessed by 01.Kernel32/Main.c, so it can copy the 64 bit kernel area to 0x200000(2MB). -
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.
-
Bootloader still load the whole image file to 0x10000 and Main.c copies the 64 bit part in memory to 0x200000
-
concatenate Kernel64.bin to Disk.img and align
-
Change in WriteKernelInformation definition
- Because Main.c utilizes
KERNEL32SECTORCOUNT
constant, ImageMaker modified the value to the number of sectors of Kernel32.bin
- Because Main.c utilizes