📄 loader.c
字号:
/*
* ################### IMPORTANT ######################
* Use watcom C/C++ to compile,
* this program needs DOS4GW.
* #####################################################
*/
#include <stdio.h>
#define HIGH_OFFSET 0x800000
char *bootsect_pos = (char *)(0x90000 + HIGH_OFFSET);
char *setup_pos = (char *)(0x90200 + HIGH_OFFSET);
char *kern_pos = (char *)(0x100000 + HIGH_OFFSET);
char *initrd_pos = (char *)(0x500000 + HIGH_OFFSET);
// Notice if you want to change the following macro:
// 1. Be sure that the macro KERN_LEN in cpboot.asm is equal
// to the macor MAX_KERNEL_SIZE.
// 2. You also need to change initrd_pos to a new safe position
// for fear kernel might be overlayed by initrd image.
#define MAX_KERNEL_SIZE ((int)initrd_pos - (int)kern_pos)
char *command_line = (char *)(0x99000 + HIGH_OFFSET);
// noinitrd is a useful kernel parameter for initrd debugging,
// I use the following command line to boot, so I can dump the
// initrd image by command dd if=/dev/initrd of=dumprd bs=xxx count=xxx.
// This is my command line for debugging.
// "root=/dev/hda9 ro noinitrd";
char my_cmd[256];
char my_linux[256];
char my_initrd[256];
// 0x01,0x01 is /dev/ram1, 0x03, 0x09 is /dev/hda9
char root_major, root_minor;
void print_usage()
{
printf("USAGE: loader kernel_image command_line\n");
}
void get_cmdline(char *my_cmd, char *const argv[])
{
argv += 2;
my_cmd[0] = 0;
while (*argv != NULL) {
strcat(my_cmd, *argv);
if (argv++) {
strcat(my_cmd, " ");
}
}
}
int get_param(const char *param, char *value, char *const argv[])
{
int e_pos;
value[0] = '\0';
argv += 2;
while (*argv != NULL) {
e_pos = strcspn(*argv, "=");
if (e_pos != strlen(*argv)) {
if (strncmp(param, *argv, e_pos) == 0) {
strcpy(value, *argv + e_pos + 1);
return 0;
}
}
argv++;
}
return 1; // parameter not found
}
int get_orig_root(char *const argv[])
{
char root_dev[256];
int devnum = 0;
if (get_param("root", root_dev, argv) == 1) {
return 1;
}
if (strcmp(root_dev, "/dev/ram") == 0) {
root_major = 0x01;
root_minor = 0x01;
return 0;
}
if (strncmp(root_dev, "/dev/hd", 7) == 0) {
switch (root_dev[7]) {
case 'a':
root_major = 3;
root_minor = 0;
break;
case 'b':
root_major = 3;
root_minor = 64;
break;
case 'c':
root_major = 22;
root_minor = 0;
break;
case 'd':
root_major = 22;
root_minor = 64;
break;
default:
return 1;
}
sscanf(root_dev + 8, "%d", &devnum);
root_minor += devnum;
return 0;
}
return 1; // ORIG_ROOT_DEV not specifeid
}
int main(int argc, char *const argv [], char *const envp[])
{
FILE *fp;
int num, i, initrd_size;
unsigned char setup_sects;
if (argc < 2) {
print_usage();
return 0;
}
// Get linux kernel name
strncpy(my_linux, argv[1], 256);
// Get linux kernel command line
get_cmdline(my_cmd, argv);
// Open the linux kernel file
fp = fopen(my_linux, "rb");
if (!fp) {
printf("Error opening linux kernel!\n");
return -1;
}
// Load kernel boot sector, only for historical reasons.
// In fact, almost no one use it to boot the kernel.
num = fread(bootsect_pos, 1, 512, fp);
if (num != 512) {
printf("Error in reading boot sector!\n");
return -1;
}
printf("Bootsect had been loaded at %XH\n", bootsect_pos);
// Get the numbers of sectors of setup section.
setup_sects = bootsect_pos[0x1f1];
// Load setup section
num = fread(setup_pos, 512 * setup_sects, 1, fp);
if (num != 1) {
printf("Error in read setup section!\n");
return -1;
}
printf("Setup had been loaded at %XH, %d bytes.\n",
setup_pos, setup_sects * 512);
printf("Load kern to %XH\n", kern_pos);
// Load protected mode kernel
num = 0;
while (!feof(fp)) {
num += fread(kern_pos, 1, 1024, fp);
kern_pos += 1024;
}
printf("%d bytes loaded.\n", num);
// If you insist to load HUGE kernel, read the comment above
// the definition of MAX_KERNEL_SIZE before change.
if (num > MAX_KERNEL_SIZE) {
printf("Error: Kernel size excceed the MAX_KERNEL_SIZE!\n");
return -1;
}
// Kernel loading finished here, close the file.
fclose(fp);
if (get_param("initrd", my_initrd, argv) == 0) {
// Load initrd image
fp = fopen(my_initrd, "rb");
if (!fp) {
printf("Error opening initrd file, no initrd?\n");
}
else {
// Load initrd image.
printf("Load initrd to %XH.\n", initrd_pos);
// Setting initrd position in the physical memory.
((int *)&(bootsect_pos[0x218]))[0] = (int)initrd_pos;
num = 0;
while (!feof(fp)) {
num += fread(initrd_pos, 1, 1024, fp);
initrd_pos += 1024;
}
printf("%d bytes loaded.\n", num);
printf("Now we set initrd position and length.\n");
// Setting initrd length in bytes.
((int *)&(bootsect_pos[0x21c]))[0] = num;
// Close the initrd file
fclose(fp);
}
}
printf("Setting up kernel command line: %s\n", my_cmd);
for (i = 0; i < 256; i++) command_line[i] = '\0';
strcpy(command_line, my_cmd);
printf("Now kernel command line is %s\n", command_line);
// Set pointer to command line
((int *)&(bootsect_pos[0x228]))[0] = 0x99000;
// Setting up kernel loader flags, 0xff means a loader unknown.
printf("Set kernel loader flag in setup section to 0xff (UNKNOWN).\n");
bootsect_pos[0x210] = 0xff;
// Setting up kernel root device, a good loader must translate it
// from command line into major and minor device numbers.
if (get_orig_root(argv) == 0) {
printf("Set up ORIG_ROOT_DEV.\n");
bootsect_pos[0x1fc] = root_minor;
bootsect_pos[0x1fd] = root_major;
printf("ROOT is %d : %d \n", root_major, root_minor);
}
printf("Use cpboot program to boot linux!\n");
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -