* Copyright 2018, JΓ©rΓ΄me Duval, jerome.duval@gmail.com.
* Distributed under the terms of the MIT License.
*/
#include "arch/x86/arch_altcodepatch.h"
#include <stdlib.h>
#include <string.h>
#include <KernelExport.h>
#include <elf.h>
#include <kernel.h>
#include <vm_defs.h>
typedef struct altcodepatch {
uint32 kernel_offset;
uint16 length;
uint16 tag;
} altcodepatch;
extern altcodepatch altcodepatch_begin;
extern altcodepatch altcodepatch_end;
void
arch_altcodepatch_replace(uint16 tag, void* newcodepatch, size_t length)
{
uint32 count = 0;
struct elf_image_info* info = elf_get_kernel_image();
const uint32 kernelProtection = B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA;
set_area_protection(info->text_region.id, kernelProtection | B_KERNEL_WRITE_AREA);
for (altcodepatch* patch = &altcodepatch_begin; patch < &altcodepatch_end;
patch++) {
if (patch->tag != tag)
continue;
void* address = (void*)(KERNEL_LOAD_BASE + patch->kernel_offset);
if (patch->length < length)
panic("can't copy patch: new code is too long\n");
memcpy(address, newcodepatch, length);
count++;
}
set_area_protection(info->text_region.id, kernelProtection);
dprintf("arch_altcodepatch_replace found %" B_PRIu32 " altcodepatches "
"for tag %u\n", count, tag);
}