diff --git a/headers/private/kernel/arch/x86/arch_altcodepatch.h b/headers/private/kernel/arch/x86/arch_altcodepatch.h new file mode 100644 index 0000000000..f8e8961501 --- /dev/null +++ b/headers/private/kernel/arch/x86/arch_altcodepatch.h @@ -0,0 +1,51 @@ +/* + * Copyright 2018, Jérôme Duval, jerome.duval@gmail.com. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_x86_ALTCODEPATCH_H +#define _KERNEL_ARCH_x86_ALTCODEPATCH_H + + +#include + + +#define ASM_NOP1 .byte 0x90 +#define ASM_NOP2 .byte 0x66, 0x90 +#define ASM_NOP3 .byte 0x0f, 0x1f, 0x00 +#define ASM_NOP4 .byte 0x0f, 0x1f, 0x40, 0x00 +#define ASM_NOP5 .byte 0x0f, 0x1f, 0x44, 0x00, 0x00 +#define ASM_NOP6 .byte 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 +#define ASM_NOP7 .byte 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 +#define ASM_NOP8 .byte 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 +#define ASM_NOP9 .byte 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 + + +#ifdef _ASSEMBLER + +#define CODEPATCH_START 990: +#define CODEPATCH_END(tag) 991: \ + .pushsection .altcodepatch, "a" ; \ + .long (990b - KERNEL_LOAD_BASE) ; \ + .short (991b - 990b) ; \ + .short tag ; \ + .popsection + +#else + +#define _STRINGIFY(x...) #x +#define STRINGIFY(x...) _STRINGIFY(x) + +#define CODEPATCH_START "990: \n" +#define CODEPATCH_END(tag) "991: \n" \ + ".pushsection .altcodepatch, \"a\" \n" \ + ".long (990b - " STRINGIFY(KERNEL_LOAD_BASE) ") \n" \ + ".short (991b - 990b) \n" \ + ".short " STRINGIFY(tag) " \n" \ + ".popsection" + +void arch_altcodepatch_replace(uint16 tag, void* newcodepatch, size_t length); + + +#endif + +#endif /* _KERNEL_ARCH_x86_ALTCODEPATCH_H */ diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index c56cc50eec..dd068ac875 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -72,6 +72,7 @@ if $(TARGET_ARCH) = x86_64 { } local archGenericSources = + arch_altcodepatch.cpp arch_cpu.cpp arch_commpage.cpp arch_debug.cpp diff --git a/src/system/kernel/arch/x86/arch_altcodepatch.cpp b/src/system/kernel/arch/x86/arch_altcodepatch.cpp new file mode 100644 index 0000000000..491ce00351 --- /dev/null +++ b/src/system/kernel/arch/x86/arch_altcodepatch.cpp @@ -0,0 +1,48 @@ +/* + * 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 +#include + +#include + +#include + + + +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; + + for (altcodepatch *patch = &altcodepatch_begin; patch < &altcodepatch_end; + patch++) { + if (patch->tag != tag) + continue; + addr_t address = KERNEL_LOAD_BASE + patch->kernel_offset; + if (patch->length < length) + panic("can't copy patch: new code is too long\n"); + memcpy((void*)address, newcodepatch, length); + count++; + } + dprintf("arch_altcodepatch_replace found %d altcodepatches\n", count); +} + + + diff --git a/src/system/ldscripts/x86/kernel.ld b/src/system/ldscripts/x86/kernel.ld index 37f6bd71e6..f5a0a821de 100644 --- a/src/system/ldscripts/x86/kernel.ld +++ b/src/system/ldscripts/x86/kernel.ld @@ -39,6 +39,11 @@ SECTIONS .rodata : { *(.rodata) } + . = ALIGN(0x4); + altcodepatch_begin = .; + .altcodepatch : { *(.altcodepatch) } + altcodepatch_end = .; + /* writable data */ . = ALIGN(0x1000); __data_start = .; diff --git a/src/system/ldscripts/x86_64/kernel.ld b/src/system/ldscripts/x86_64/kernel.ld index 5b454248db..e6b09de3d4 100644 --- a/src/system/ldscripts/x86_64/kernel.ld +++ b/src/system/ldscripts/x86_64/kernel.ld @@ -28,6 +28,11 @@ SECTIONS .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + . = ALIGN(0x8); + altcodepatch_begin = .; + .altcodepatch : { *(.altcodepatch) } + altcodepatch_end = .; + /* writable data */ . = ALIGN (0x1000); __data_start = .;