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
20typedef struct altcodepatch {
21	uint32 kernel_offset;
22	uint16 length;
23	uint16 tag;
24} altcodepatch;
25
26
27extern altcodepatch altcodepatch_begin;
28extern altcodepatch altcodepatch_end;
29
30
31void
32arch_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 "
56		"for tag %u\n", count, tag);
57}
58
59