arch/x86/kernel/kexec-bzimage64.c

Source file repositories/reference/linux-study-clean/arch/x86/kernel/kexec-bzimage64.c

File Facts

System
Linux kernel
Corpus path
arch/x86/kernel/kexec-bzimage64.c
Extension
.c
Size
20760 bytes
Lines
722
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct bzimage64_data {
	/*
	 * Temporary buffer to hold bootparams buffer. This should be
	 * freed once the bootparam segment has been loaded.
	 */
	void *bootparams_buf;
};

static int setup_initrd(struct boot_params *params,
		unsigned long initrd_load_addr, unsigned long initrd_len)
{
	params->hdr.ramdisk_image = initrd_load_addr & 0xffffffffUL;
	params->hdr.ramdisk_size = initrd_len & 0xffffffffUL;

	params->ext_ramdisk_image = initrd_load_addr >> 32;
	params->ext_ramdisk_size = initrd_len >> 32;

	return 0;
}

static int setup_cmdline(struct kimage *image, struct boot_params *params,
			 unsigned long bootparams_load_addr,
			 unsigned long cmdline_offset, char *cmdline,
			 unsigned long cmdline_len)
{
	char *cmdline_ptr = ((char *)params) + cmdline_offset;
	unsigned long cmdline_ptr_phys, len = 0;
	uint32_t cmdline_low_32, cmdline_ext_32;

	if (image->type == KEXEC_TYPE_CRASH) {
		len = sprintf(cmdline_ptr,
			"elfcorehdr=0x%lx ", image->elf_load_addr);

		if (image->dm_crypt_keys_addr != 0)
			len += sprintf(cmdline_ptr + len,
					"dmcryptkeys=0x%lx ", image->dm_crypt_keys_addr);
	}
	memcpy(cmdline_ptr + len, cmdline, cmdline_len);
	cmdline_len += len;

	cmdline_ptr[cmdline_len - 1] = '\0';

	kexec_dprintk("Final command line is: %s\n", cmdline_ptr);
	cmdline_ptr_phys = bootparams_load_addr + cmdline_offset;
	cmdline_low_32 = cmdline_ptr_phys & 0xffffffffUL;
	cmdline_ext_32 = cmdline_ptr_phys >> 32;

	params->hdr.cmd_line_ptr = cmdline_low_32;
	if (cmdline_ext_32)
		params->ext_cmd_line_ptr = cmdline_ext_32;

	return 0;
}

static int setup_e820_entries(struct boot_params *params)
{
	unsigned int nr_e820_entries;

	nr_e820_entries = e820_table_kexec->nr_entries;

	/* TODO: Pass entries more than E820_MAX_ENTRIES_ZEROPAGE in bootparams setup data */
	if (nr_e820_entries > E820_MAX_ENTRIES_ZEROPAGE)
		nr_e820_entries = E820_MAX_ENTRIES_ZEROPAGE;

	params->e820_entries = nr_e820_entries;
	memcpy(&params->e820_table, &e820_table_kexec->entries, nr_e820_entries*sizeof(struct e820_entry));

	return 0;
}

enum { RNG_SEED_LENGTH = 32 };

static void
setup_rng_seed(struct boot_params *params, unsigned long params_load_addr,
	       unsigned int rng_seed_setup_data_offset)
{
	struct setup_data *sd = (void *)params + rng_seed_setup_data_offset;
	unsigned long setup_data_phys;

	if (!rng_is_initialized())
		return;

	sd->type = SETUP_RNG_SEED;
	sd->len = RNG_SEED_LENGTH;
	get_random_bytes(sd->data, RNG_SEED_LENGTH);
	setup_data_phys = params_load_addr + rng_seed_setup_data_offset;
	sd->next = params->hdr.setup_data;
	params->hdr.setup_data = setup_data_phys;
}

Annotation

Implementation Notes