1 /* 2 * Copyright 2018, Jérôme Duval, jerome.duval@gmail.com. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "arch/x86/arch_altcodepatch.h" 8 9 #include <stdlib.h> 10 #include <string.h> 11 12 #include <KernelExport.h> 13 14 #include <elf.h> 15 #include <kernel.h> 16 #include <vm_defs.h> 17 18 19 20 typedef struct altcodepatch { 21 uint32 kernel_offset; 22 uint16 length; 23 uint16 tag; 24 } altcodepatch; 25 26 27 extern altcodepatch altcodepatch_begin; 28 extern altcodepatch altcodepatch_end; 29 30 31 void 32 arch_altcodepatch_replace(uint16 tag, void* newcodepatch, size_t length) 33 { 34 uint32 count = 0; 35 36 // we need to write to the text area 37 struct elf_image_info* info = elf_get_kernel_image(); 38 const uint32 kernelProtection = B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA; 39 set_area_protection(info->text_region.id, kernelProtection | B_KERNEL_WRITE_AREA); 40 41 for (altcodepatch* patch = &altcodepatch_begin; patch < &altcodepatch_end; 42 patch++) { 43 if (patch->tag != tag) 44 continue; 45 void* address = (void*)(KERNEL_LOAD_BASE + patch->kernel_offset); 46 if (patch->length < length) 47 panic("can't copy patch: new code is too long\n"); 48 memcpy(address, newcodepatch, length); 49 count++; 50 } 51 52 // disable write after patch 53 set_area_protection(info->text_region.id, kernelProtection); 54 55 dprintf("arch_altcodepatch_replace found %" B_PRIu32 " altcodepatches\n", count); 56 } 57 58