func SetupLinuxBootParams(
	model *machine.Model,
	boot_params_data []byte,
	orig_boot_params_data []byte,
	cmdline_addr platform.Paddr,
	initrd_addr platform.Paddr,
	initrd_len uint64) error {

	// Grab a reference to our boot params struct.
	boot_params := (*C.struct_boot_params)(unsafe.Pointer(&boot_params_data[0]))

	// The setup header.
	// First step is to copy the existing setup_header
	// out of the given kernel image. We copy only the
	// header, and not the rest of the setup page.
	setup_start := 0x01f1
	setup_end := 0x0202 + int(orig_boot_params_data[0x0201])
	if setup_end > platform.PageSize {
		return InvalidSetupHeader
	}
	C.memcpy(
		unsafe.Pointer(&boot_params_data[setup_start]),
		unsafe.Pointer(&orig_boot_params_data[setup_start]),
		C.size_t(setup_end-setup_start))

	// Setup our BIOS memory map.
	// NOTE: We have to do this via C bindings. This is really
	// annoying, but basically because of the unaligned structures
	// in the struct_boot_params, the Go code generated here is
	// actually *incompatible* with the actual C layout.

	// First, the count.
	C.e820_set_count(boot_params, C.int(len(model.MemoryMap)))

	// Then, fill out the region information.
	for index, region := range model.MemoryMap {

		var memtype C.int
		switch region.MemoryType {
		case machine.MemoryTypeUser:
			memtype = C.E820Ram
		case machine.MemoryTypeReserved:
			memtype = C.E820Reserved
		case machine.MemoryTypeSpecial:
			memtype = C.E820Reserved
		case machine.MemoryTypeAcpi:
			memtype = C.E820Acpi
		}

		C.e820_set_region(
			boot_params,
			C.int(index),
			C.__u64(region.Start),
			C.__u64(region.Size),
			C.__u8(memtype))
	}

	// Set necessary setup header bits.
	C.set_header(
		boot_params,
		C.__u64(initrd_addr),
		C.__u64(initrd_len),
		C.__u64(cmdline_addr))

	// All done!
	return nil
}
Beispiel #2
0
func Set_header(s unsafe.Pointer, key string, value string) {
	key_ptr := to_ptr(key)
	value_ptr := to_ptr(value)
	C.set_header((*C.servlet)(s), (*C.char)(key_ptr), (*C.char)(value_ptr))
}