/* * purgatory: setup code * * Copyright (C) 2005-2006 Zou Nan hai (nanhai.zou@intel.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation (version 2 of the License). * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "purgatory-ia64.h" #define PAGE_OFFSET 0xe000000000000000UL #define EFI_PAGE_SHIFT 12 #define EFI_PAGE_SIZE (1UL<efi_memmap_base; void *src = (void *)boot_param->efi_memmap; unsigned long len = boot_param->efi_memmap_size; unsigned long memdesc_size = boot_param->efi_memdesc_size; uint64_t orig_type; efi_memory_desc_t *md1, *md2; void *p1, *p2, *src_end = src + len; int i; for (p1 = src, p2 = dest; p1 < src_end; p1 += memdesc_size, p2 += memdesc_size) { unsigned long mstart, mend; md1 = p1; md2 = p2; if (md1->num_pages == 0) continue; mstart = md1->phys_addr; mend = md1->phys_addr + (md1->num_pages << EFI_PAGE_SHIFT); switch (md1->type) { case EFI_LOADER_DATA: *md2 = *md1; md2->type = EFI_CONVENTIONAL_MEMORY; break; default: *md2 = *md1; } // segments are already sorted and aligned to 4K orig_type = md2->type; for (i = 0; i < params->loaded_segments_num; i++) { struct loaded_segment *seg; seg = ¶ms->loaded_segments[i]; if (seg->start >= mstart && seg->start < mend) { unsigned long start_pages, mid_pages, end_pages; if (seg->end > mend) { p1 += memdesc_size; for(; p1 < src_end; p1 += memdesc_size) { md1 = p1; /* TODO check contig and attribute here */ mend = md1->phys_addr + (md1->num_pages << EFI_PAGE_SHIFT); if (seg->end < mend) break; } } start_pages = (seg->start - mstart) >> EFI_PAGE_SHIFT; mid_pages = (seg->end - seg->start) >> EFI_PAGE_SHIFT; end_pages = (mend - seg->end) >> EFI_PAGE_SHIFT; if (start_pages) { md2->num_pages = start_pages; p2 += memdesc_size; md2 = p2; *md2 = *md1; } md2->phys_addr = seg->start; md2->num_pages = mid_pages; md2->type = seg->reserved ? EFI_UNUSABLE_MEMORY:EFI_LOADER_DATA; if (end_pages) { p2 += memdesc_size; md2 = p2; *md2 = *md1; md2->phys_addr = seg->end; md2->num_pages = end_pages; md2->type = orig_type; mstart = seg->end; } else break; } } } boot_param->efi_memmap_size = p2 - dest; } void flush_icache_range(char *start, unsigned long len) { unsigned long i; for (i = 0;i < len; i += 32) asm volatile("fc.i %0"::"r"(start + i):"memory"); asm volatile (";;sync.i;;":::"memory"); asm volatile ("srlz.i":::"memory"); } extern char __dummy_efi_function[], __dummy_efi_function_end[]; void ia64_env_setup(struct ia64_boot_param *boot_param, struct kexec_boot_params *params) { unsigned long len; efi_system_table_t *systab; efi_runtime_services_t *runtime; unsigned long *set_virtual_address_map; char *command_line = (char *)params->command_line; uint64_t command_line_len = params->command_line_len; // patch efi_runtime->set_virtual_address_map to a // dummy function len = __dummy_efi_function_end - __dummy_efi_function; memcpy(command_line + command_line_len, __dummy_efi_function, len); systab = (efi_system_table_t *)boot_param->efi_systab; runtime = (efi_runtime_services_t *)PA(systab->runtime); set_virtual_address_map = (unsigned long *)PA(runtime->set_virtual_address_map); *(set_virtual_address_map) = (unsigned long)(command_line + command_line_len); flush_icache_range(command_line + command_line_len, len); patch_efi_memmap(params, boot_param); boot_param->efi_memmap = params->efi_memmap_base; boot_param->command_line = params->command_line; boot_param->console_info.orig_x = 0; boot_param->console_info.orig_y = 0; boot_param->initrd_start = params->ramdisk_base; boot_param->initrd_size = params->ramdisk_size; } /* This function can be used to execute after the SHA256 verification. */ void post_verification_setup_arch(void) { /* Nothing for now */ }