⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader.c

📁 这是bootloader源码
💻 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 + -