summaryrefslogtreecommitdiff
path: root/common_modules
diff options
context:
space:
mode:
authorFrédéric Desbiens <[email protected]>2026-10-02 10:42:44 -0400
committerGitHub <[email protected]>2026-10-02 10:42:44 -0400
commit93387b0a60382a29579bbad5045c68328e3751df (patch)
tree42be790d602cb76f55090e5a7c418df7ea2b3428 /common_modules
parent44d7c95c582d415c4ad84527180b29c93c3bf664 (diff)
parent28281cd5647d4671236ca08d19bd18ed15b2265a (diff)
Merge pull request #783 from eclipse-threadx/devv6.5.2.202603_rel
Merged changes ahead of the v6.5.2.202603 release
Diffstat (limited to 'common_modules')
-rw-r--r--common_modules/inc/txm_module.h6
-rw-r--r--common_modules/module_lib/src/txm_block_pool_create.c4
-rw-r--r--common_modules/module_lib/src/txm_block_pool_info_get.c4
-rw-r--r--common_modules/module_lib/src/txm_byte_pool_create.c4
-rw-r--r--common_modules/module_lib/src/txm_byte_pool_info_get.c4
-rw-r--r--common_modules/module_lib/src/txm_event_flags_create.c4
-rw-r--r--common_modules/module_lib/src/txm_event_flags_info_get.c4
-rw-r--r--common_modules/module_lib/src/txm_module_object_deallocate.c30
-rw-r--r--common_modules/module_lib/src/txm_module_object_pointer_get.c23
-rw-r--r--common_modules/module_lib/src/txm_mutex_create.c4
-rw-r--r--common_modules/module_lib/src/txm_mutex_info_get.c4
-rw-r--r--common_modules/module_lib/src/txm_queue_create.c4
-rw-r--r--common_modules/module_lib/src/txm_queue_info_get.c4
-rw-r--r--common_modules/module_lib/src/txm_semaphore_create.c4
-rw-r--r--common_modules/module_lib/src/txm_semaphore_info_get.c4
-rw-r--r--common_modules/module_lib/src/txm_thread_create.c4
-rw-r--r--common_modules/module_lib/src/txm_thread_info_get.c4
-rw-r--r--common_modules/module_lib/src/txm_timer_create.c4
-rw-r--r--common_modules/module_lib/src/txm_timer_info_get.c4
-rw-r--r--common_modules/module_manager/inc/txm_module_manager_dispatch.h296
-rw-r--r--common_modules/module_manager/inc/txm_module_manager_util.h86
-rw-r--r--common_modules/module_manager/src/txm_module_manager_absolute_load.c417
-rw-r--r--common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c486
-rw-r--r--common_modules/module_manager/src/txm_module_manager_object_allocate.c27
-rw-r--r--common_modules/module_manager/src/txm_module_manager_object_deallocate.c108
-rw-r--r--common_modules/module_manager/src/txm_module_manager_object_pointer_get.c7
-rw-r--r--common_modules/module_manager/src/txm_module_manager_thread_create.c48
-rw-r--r--common_modules/module_manager/src/txm_module_manager_thread_reset.c16
-rw-r--r--common_modules/module_manager/src/txm_module_manager_util.c1023
-rw-r--r--common_modules/module_manager/utilities/module_binary_to_c_array.c30
-rw-r--r--common_modules/module_manager/utilities/module_to_binary.c230
-rw-r--r--common_modules/module_manager/utilities/module_to_c_array.c238
32 files changed, 2531 insertions, 604 deletions
diff --git a/common_modules/inc/txm_module.h b/common_modules/inc/txm_module.h
index 88f79d9e..a823c2c0 100644
--- a/common_modules/inc/txm_module.h
+++ b/common_modules/inc/txm_module.h
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -569,6 +571,7 @@ VOID _txm_module_usbx_duo_callback_request(TXM_MODULE_CALLBACK_MESSAGE *callbac
#define txm_module_manager_initialize _txm_module_manager_initialize
#define txm_module_manager_absolute_load _txm_module_manager_absolute_load
+#define txm_module_manager_absolute_load_extended _txm_module_manager_absolute_load_extended
#define txm_module_manager_in_place_load _txm_module_manager_in_place_load
#define txm_module_manager_file_load _txm_module_manager_file_load
#define txm_module_manager_memory_load _txm_module_manager_memory_load
@@ -606,6 +609,7 @@ UINT _txm_module_manager_file_load(TXM_MODULE_INSTANCE *module_instance, CHAR *
#endif
UINT _txm_module_manager_initialize(VOID *module_memory_start, ULONG module_memory_size);
UINT _txm_module_manager_absolute_load(TXM_MODULE_INSTANCE *module_instance, CHAR *name, VOID *module_location);
+UINT _txm_module_manager_absolute_load_extended(TXM_MODULE_INSTANCE *module_instance, CHAR *name, VOID *module_location, VOID *module_data_location);
UINT _txm_module_manager_in_place_load(TXM_MODULE_INSTANCE *module_instance, CHAR *name, VOID *module_location);
UINT _txm_module_manager_internal_load(TXM_MODULE_INSTANCE *module_instance, CHAR *name, VOID *module_location,
ULONG code_size, VOID *code_allocation_ptr, ULONG code_allocation_size);
@@ -620,7 +624,7 @@ UINT _txm_module_manager_memory_load(TXM_MODULE_INSTANCE *module_instance, CHAR
UINT _txm_module_manager_properties_get(TXM_MODULE_INSTANCE *module_instance, ULONG *module_properties_ptr);
UINT _txm_module_manager_start(TXM_MODULE_INSTANCE *module_instance);
UINT _txm_module_manager_stop(TXM_MODULE_INSTANCE *module_instance);
-UINT _txm_module_manager_thread_create(TX_THREAD *thread_ptr, CHAR *name, VOID (*shell_function)(TX_THREAD *, TXM_MODULE_INSTANCE *),
+UINT _txm_module_manager_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name, VOID (*shell_function)(TX_THREAD *, TXM_MODULE_INSTANCE *),
VOID (*entry_function)(ULONG), ULONG entry_input,
VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold,
ULONG time_slice, UINT auto_start, UINT thread_control_block_size, TXM_MODULE_INSTANCE *module_instance);
diff --git a/common_modules/module_lib/src/txm_block_pool_create.c b/common_modules/module_lib/src/txm_block_pool_create.c
index 90838e3b..aa9a6180 100644
--- a/common_modules/module_lib/src/txm_block_pool_create.c
+++ b/common_modules/module_lib/src/txm_block_pool_create.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -64,7 +66,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size)
+UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_block_pool_info_get.c b/common_modules/module_lib/src/txm_block_pool_info_get.c
index fa4ea686..944281e3 100644
--- a/common_modules/module_lib/src/txm_block_pool_info_get.c
+++ b/common_modules/module_lib/src/txm_block_pool_info_get.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -64,7 +66,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool)
+UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_byte_pool_create.c b/common_modules/module_lib/src/txm_byte_pool_create.c
index d7775e3f..d0cc76c6 100644
--- a/common_modules/module_lib/src/txm_byte_pool_create.c
+++ b/common_modules/module_lib/src/txm_byte_pool_create.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -63,7 +65,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size)
+UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_byte_pool_info_get.c b/common_modules/module_lib/src/txm_byte_pool_info_get.c
index 1ad38f48..d6b4a3d6 100644
--- a/common_modules/module_lib/src/txm_byte_pool_info_get.c
+++ b/common_modules/module_lib/src/txm_byte_pool_info_get.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -64,7 +66,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool)
+UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_event_flags_create.c b/common_modules/module_lib/src/txm_event_flags_create.c
index 76f1fe31..b4e155c1 100644
--- a/common_modules/module_lib/src/txm_event_flags_create.c
+++ b/common_modules/module_lib/src/txm_event_flags_create.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -60,7 +62,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size)
+UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr, UINT event_control_block_size)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_event_flags_info_get.c b/common_modules/module_lib/src/txm_event_flags_info_get.c
index eedcce1f..ebcee339 100644
--- a/common_modules/module_lib/src/txm_event_flags_info_get.c
+++ b/common_modules/module_lib/src/txm_event_flags_info_get.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -65,7 +67,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group)
+UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_module_object_deallocate.c b/common_modules/module_lib/src/txm_module_object_deallocate.c
index c0ffb097..fa5ebe85 100644
--- a/common_modules/module_lib/src/txm_module_object_deallocate.c
+++ b/common_modules/module_lib/src/txm_module_object_deallocate.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -23,6 +25,31 @@
#define TXM_MODULE
#include "txm_module.h"
#ifndef TXM_MODULE_OBJECT_DEALLOCATE_CALL_NOT_USED
+
+/* DEPRECATION NOTICE
+ * txm_module_object_deallocate() is deprecated and must not be used in new
+ * code. It is retained only for backward-compatibility with existing modules.
+ *
+ * WHY: when a module calls tx_timer_delete(), tx_semaphore_delete(), or any
+ * other tx_*_delete() service, the Module Manager dispatch layer automatically
+ * releases the associated object pool memory after the kernel cleanup
+ * completes. No separate deallocation call is required or expected.
+ *
+ * WHAT TO DO: remove any call to txm_module_object_deallocate() from your
+ * module. The corresponding tx_*_delete() call already handles everything.
+ *
+ * BEHAVIOUR: calling txm_module_object_deallocate() on a live kernel object
+ * (one whose tx_*_delete() has not yet been called) returns TX_DELETE_ERROR
+ * and changes nothing. The Module Manager will not release the memory of a
+ * created object, because the kernel goes on using those bytes as a control
+ * block after the byte pool has handed them to somebody else. Storage that
+ * was allocated but never made into an object is still released, so cleaning
+ * up after a create that failed or was abandoned still works.
+ */
+#pragma message("txm_module_object_deallocate() is deprecated and must not be used. " \
+ "Call tx_*_delete() instead; the Module Manager dispatch layer " \
+ "releases pool memory automatically on success. Deallocating a " \
+ "live kernel object returns TX_DELETE_ERROR.")
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
@@ -43,7 +70,8 @@
/* */
/* OUTPUT */
/* */
-/* status Completion status */
+/* status Completion status, TX_DELETE_ERROR*/
+/* if a live object is there */
/* */
/* CALLS */
/* */
diff --git a/common_modules/module_lib/src/txm_module_object_pointer_get.c b/common_modules/module_lib/src/txm_module_object_pointer_get.c
index 6417457a..fcd7ab1f 100644
--- a/common_modules/module_lib/src/txm_module_object_pointer_get.c
+++ b/common_modules/module_lib/src/txm_module_object_pointer_get.c
@@ -23,6 +23,22 @@
#define TXM_MODULE
#include "txm_module.h"
#ifndef TXM_MODULE_OBJECT_POINTER_GET_CALL_NOT_USED
+
+/* DEPRECATION NOTICE
+ * txm_module_object_pointer_get() is deprecated. Do not use it in new code.
+ *
+ * WHY: this function passes UINT_MAX as the name-buffer length to the
+ * underlying search. If the name pointer points to a buffer shorter than
+ * the searched string, the comparison can read past the end of the buffer,
+ * which is undefined behaviour.
+ *
+ * WHAT TO DO: replace calls with txm_module_object_pointer_get_extended(),
+ * passing the actual length of the name buffer as the third argument.
+ */
+#pragma message("txm_module_object_pointer_get() is deprecated. " \
+ "Use txm_module_object_pointer_get_extended() and pass " \
+ "the actual name buffer length.")
+
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
@@ -35,9 +51,10 @@
/* */
/* DESCRIPTION */
/* */
-/* This function is deprecated and calls the secure version of this */
-/* function (_txm_module_manager_object_pointer_get_extended) with the */
-/* maximum possible name length since none was passed. */
+/* DEPRECATED. Use _txm_module_object_pointer_get_extended() instead, */
+/* passing the actual name-buffer length. This wrapper passes */
+/* UINT_MAX as the length, which can cause the name-comparison loop */
+/* to read past the end of a short buffer (undefined behaviour). */
/* */
/* INPUT */
/* */
diff --git a/common_modules/module_lib/src/txm_mutex_create.c b/common_modules/module_lib/src/txm_mutex_create.c
index f50fd52f..5dc53dd9 100644
--- a/common_modules/module_lib/src/txm_mutex_create.c
+++ b/common_modules/module_lib/src/txm_mutex_create.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -61,7 +63,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size)
+UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_mutex_info_get.c b/common_modules/module_lib/src/txm_mutex_info_get.c
index 8e63c779..534e110e 100644
--- a/common_modules/module_lib/src/txm_mutex_info_get.c
+++ b/common_modules/module_lib/src/txm_mutex_info_get.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -65,7 +67,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex)
+UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_queue_create.c b/common_modules/module_lib/src/txm_queue_create.c
index a18b9f85..982c3587 100644
--- a/common_modules/module_lib/src/txm_queue_create.c
+++ b/common_modules/module_lib/src/txm_queue_create.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -62,7 +64,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size)
+UINT _txe_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_queue_info_get.c b/common_modules/module_lib/src/txm_queue_info_get.c
index c66a3d7e..8627a45a 100644
--- a/common_modules/module_lib/src/txm_queue_info_get.c
+++ b/common_modules/module_lib/src/txm_queue_info_get.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -64,7 +66,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue)
+UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_semaphore_create.c b/common_modules/module_lib/src/txm_semaphore_create.c
index 229b46cd..fbce2d54 100644
--- a/common_modules/module_lib/src/txm_semaphore_create.c
+++ b/common_modules/module_lib/src/txm_semaphore_create.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -60,7 +62,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size)
+UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_semaphore_info_get.c b/common_modules/module_lib/src/txm_semaphore_info_get.c
index 2bdfa2c0..128afae7 100644
--- a/common_modules/module_lib/src/txm_semaphore_info_get.c
+++ b/common_modules/module_lib/src/txm_semaphore_info_get.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -64,7 +66,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore)
+UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_thread_create.c b/common_modules/module_lib/src/txm_thread_create.c
index 8b1bc367..f17a0185 100644
--- a/common_modules/module_lib/src/txm_thread_create.c
+++ b/common_modules/module_lib/src/txm_thread_create.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -70,7 +72,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start, UINT thread_control_block_size)
+UINT _txe_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start, UINT thread_control_block_size)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_thread_info_get.c b/common_modules/module_lib/src/txm_thread_info_get.c
index d956c031..e50fc446 100644
--- a/common_modules/module_lib/src/txm_thread_info_get.c
+++ b/common_modules/module_lib/src/txm_thread_info_get.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -67,7 +69,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread)
+UINT _txe_thread_info_get(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_timer_create.c b/common_modules/module_lib/src/txm_timer_create.c
index d65989eb..7adba901 100644
--- a/common_modules/module_lib/src/txm_timer_create.c
+++ b/common_modules/module_lib/src/txm_timer_create.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -65,7 +67,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, VOID (*expiration_function)(ULONG), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size)
+UINT _txe_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size)
{
UINT return_value;
diff --git a/common_modules/module_lib/src/txm_timer_info_get.c b/common_modules/module_lib/src/txm_timer_info_get.c
index f918ca67..d431ed93 100644
--- a/common_modules/module_lib/src/txm_timer_info_get.c
+++ b/common_modules/module_lib/src/txm_timer_info_get.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+/* Portions of this file were generated with AI assistance. */
+
/**************************************************************************/
/**************************************************************************/
@@ -63,7 +65,7 @@
/* Module application code */
/* */
/**************************************************************************/
-UINT _txe_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer)
+UINT _txe_timer_info_get(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer)
{
UINT return_value;
diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h
index 03bd86eb..e8c0629b 100644
--- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h
+++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h
@@ -1,6 +1,7 @@
/***************************************************************************
* Copyright (c) 2024 Microsoft Corporation
* Copyright (c) 2025 Eclipse ThreadX Contributors
+ * Copyright (c) 2026 Eclipse ThreadX contributors
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
@@ -8,6 +9,7 @@
*
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
/**************************************************************************/
@@ -33,7 +35,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(VOID *)))
@@ -52,7 +54,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_BLOCK_POOL_CREATE_CALL_NOT_USED
/* UINT _txe_block_pool_create(
TX_BLOCK_POOL *pool_ptr, -> param_0
- CHAR *name_ptr, -> param_1
+ TX_NAME_CONST CHAR *name_ptr, -> param_1
ULONG block_size, -> extra_parameters[0]
VOID *pool_start, -> extra_parameters[1]
ULONG pool_size, -> extra_parameters[2]
@@ -71,7 +73,7 @@ ALIGN_TYPE return_value;
if (!TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING(module_instance, param_1))
return(TXM_MODULE_INVALID_MEMORY);
- if (!TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, (ALIGN_TYPE)extra_parameters, sizeof(ALIGN_TYPE[2])))
+ if (!TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, (ALIGN_TYPE)extra_parameters, sizeof(ALIGN_TYPE[4])))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, extra_parameters[1], extra_parameters[2]))
@@ -80,7 +82,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_block_pool_create(
(TX_BLOCK_POOL *) param_0,
- (CHAR *) param_1,
+ (TX_NAME_CONST CHAR *) param_1,
(ULONG) extra_parameters[0],
(VOID *) extra_parameters[1],
(ULONG) extra_parameters[2],
@@ -101,7 +103,10 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT))
+ return(TXM_MODULE_INVALID_MEMORY);
+
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_BLOCK_POOL)))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -121,7 +126,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_BLOCK_POOL_INFO_GET_CALL_NOT_USED
/* UINT _txe_block_pool_info_get(
TX_BLOCK_POOL *pool_ptr, -> param_0
- CHAR **name, -> param_1
+ TX_NAME_CONST CHAR **name, -> param_1
ULONG *available_blocks, -> extra_parameters[0]
ULONG *total_blocks, -> extra_parameters[1]
TX_THREAD **first_suspended, -> extra_parameters[2]
@@ -135,7 +140,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -162,7 +167,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_block_pool_info_get(
(TX_BLOCK_POOL *) param_0,
- (CHAR **) param_1,
+ (TX_NAME_CONST CHAR **) param_1,
(ULONG *) extra_parameters[0],
(ULONG *) extra_parameters[1],
(TX_THREAD **) extra_parameters[2],
@@ -188,7 +193,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -269,7 +274,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -335,7 +340,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(VOID *)))
@@ -358,7 +363,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_BYTE_POOL_CREATE_CALL_NOT_USED
/* UINT _txe_byte_pool_create(
TX_BYTE_POOL *pool_ptr, -> param_0
- CHAR *name_ptr, -> param_1
+ TX_NAME_CONST CHAR *name_ptr, -> param_1
VOID *pool_start, -> extra_parameters[0]
ULONG pool_size, -> extra_parameters[1]
UINT pool_control_block_size -> extra_parameters[2]
@@ -385,7 +390,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_byte_pool_create(
(TX_BYTE_POOL *) param_0,
- (CHAR *) param_1,
+ (TX_NAME_CONST CHAR *) param_1,
(VOID *) extra_parameters[0],
(ULONG) extra_parameters[1],
(UINT) extra_parameters[2]
@@ -405,7 +410,10 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT))
+ return(TXM_MODULE_INVALID_MEMORY);
+
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_BYTE_POOL)))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -425,7 +433,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_BYTE_POOL_INFO_GET_CALL_NOT_USED
/* UINT _txe_byte_pool_info_get(
TX_BYTE_POOL *pool_ptr, -> param_0
- CHAR **name, -> param_1
+ TX_NAME_CONST CHAR **name, -> param_1
ULONG *available_bytes, -> extra_parameters[0]
ULONG *fragments, -> extra_parameters[1]
TX_THREAD **first_suspended, -> extra_parameters[2]
@@ -439,7 +447,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -466,7 +474,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_byte_pool_info_get(
(TX_BYTE_POOL *) param_0,
- (CHAR **) param_1,
+ (TX_NAME_CONST CHAR **) param_1,
(ULONG *) extra_parameters[0],
(ULONG *) extra_parameters[1],
(TX_THREAD **) extra_parameters[2],
@@ -495,7 +503,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -603,7 +611,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -658,7 +666,7 @@ ALIGN_TYPE block_header_start;
#ifndef TXM_EVENT_FLAGS_CREATE_CALL_NOT_USED
/* UINT _txe_event_flags_create(
TX_EVENT_FLAGS_GROUP *group_ptr, -> param_0
- CHAR *name_ptr, -> param_1
+ TX_NAME_CONST CHAR *name_ptr, -> param_1
UINT event_control_block_size -> param_2
); */
static ALIGN_TYPE _txm_module_manager_tx_event_flags_create_dispatch(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE param_0, ALIGN_TYPE param_1, ALIGN_TYPE param_2)
@@ -677,7 +685,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_event_flags_create(
(TX_EVENT_FLAGS_GROUP *) param_0,
- (CHAR *) param_1,
+ (TX_NAME_CONST CHAR *) param_1,
(UINT) param_2
);
return(return_value);
@@ -695,7 +703,10 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
+ return(TXM_MODULE_INVALID_MEMORY);
+
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -727,7 +738,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, extra_parameters[1], sizeof(ULONG)))
@@ -751,7 +762,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_EVENT_FLAGS_INFO_GET_CALL_NOT_USED
/* UINT _txe_event_flags_info_get(
TX_EVENT_FLAGS_GROUP *group_ptr, -> param_0
- CHAR **name, -> param_1
+ TX_NAME_CONST CHAR **name, -> param_1
ULONG *current_flags, -> extra_parameters[0]
TX_THREAD **first_suspended, -> extra_parameters[1]
ULONG *suspended_count, -> extra_parameters[2]
@@ -764,7 +775,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -788,7 +799,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_event_flags_info_get(
(TX_EVENT_FLAGS_GROUP *) param_0,
- (CHAR **) param_1,
+ (TX_NAME_CONST CHAR **) param_1,
(ULONG *) extra_parameters[0],
(TX_THREAD **) extra_parameters[1],
(ULONG *) extra_parameters[2],
@@ -813,7 +824,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -896,7 +907,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -923,7 +934,7 @@ VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *);
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* Since we need to write to the object, ensure it's valid. */
@@ -958,7 +969,7 @@ VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *);
#ifndef TXM_MUTEX_CREATE_CALL_NOT_USED
/* UINT _txe_mutex_create(
TX_MUTEX *mutex_ptr, -> param_0
- CHAR *name_ptr, -> param_1
+ TX_NAME_CONST CHAR *name_ptr, -> param_1
UINT inherit, -> extra_parameters[0]
UINT mutex_control_block_size -> extra_parameters[1]
); */
@@ -981,7 +992,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_mutex_create(
(TX_MUTEX *) param_0,
- (CHAR *) param_1,
+ (TX_NAME_CONST CHAR *) param_1,
(UINT) extra_parameters[0],
(UINT) extra_parameters[1]
);
@@ -1000,7 +1011,10 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
+ return(TXM_MODULE_INVALID_MEMORY);
+
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_MUTEX)))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1029,7 +1043,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1044,7 +1058,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_MUTEX_INFO_GET_CALL_NOT_USED
/* UINT _txe_mutex_info_get(
TX_MUTEX *mutex_ptr, -> param_0
- CHAR **name, -> param_1
+ TX_NAME_CONST CHAR **name, -> param_1
ULONG *count, -> extra_parameters[0]
TX_THREAD **owner, -> extra_parameters[1]
TX_THREAD **first_suspended, -> extra_parameters[2]
@@ -1058,7 +1072,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -1085,7 +1099,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_mutex_info_get(
(TX_MUTEX *) param_0,
- (CHAR **) param_1,
+ (TX_NAME_CONST CHAR **) param_1,
(ULONG *) extra_parameters[0],
(TX_THREAD **) extra_parameters[1],
(TX_THREAD **) extra_parameters[2],
@@ -1113,7 +1127,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -1212,7 +1226,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1234,7 +1248,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1248,7 +1262,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_QUEUE_CREATE_CALL_NOT_USED
/* UINT _txe_queue_create(
TX_QUEUE *queue_ptr, -> param_0
- CHAR *name_ptr, -> param_1
+ TX_NAME_CONST CHAR *name_ptr, -> param_1
UINT message_size, -> extra_parameters[0]
VOID *queue_start, -> extra_parameters[1]
ULONG queue_size, -> extra_parameters[2]
@@ -1276,7 +1290,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_queue_create(
(TX_QUEUE *) param_0,
- (CHAR *) param_1,
+ (TX_NAME_CONST CHAR *) param_1,
(UINT) extra_parameters[0],
(VOID *) extra_parameters[1],
(ULONG) extra_parameters[2],
@@ -1297,7 +1311,10 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
+ return(TXM_MODULE_INVALID_MEMORY);
+
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_QUEUE)))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1325,7 +1342,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1350,12 +1367,12 @@ TX_QUEUE *queue_ptr;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* We need to get the size of the message from the queue. */
queue_ptr = (TX_QUEUE *) param_0;
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_READ(module_instance, param_1, queue_ptr -> tx_queue_message_size))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_READ(module_instance, param_1, sizeof(ULONG)*queue_ptr -> tx_queue_message_size))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1371,7 +1388,7 @@ TX_QUEUE *queue_ptr;
#ifndef TXM_QUEUE_INFO_GET_CALL_NOT_USED
/* UINT _txe_queue_info_get(
TX_QUEUE *queue_ptr, -> param_0
- CHAR **name, -> param_1
+ TX_NAME_CONST CHAR **name, -> param_1
ULONG *enqueued, -> extra_parameters[0]
ULONG *available_storage, -> extra_parameters[1]
TX_THREAD **first_suspended, -> extra_parameters[2]
@@ -1385,7 +1402,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -1412,7 +1429,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_queue_info_get(
(TX_QUEUE *) param_0,
- (CHAR **) param_1,
+ (TX_NAME_CONST CHAR **) param_1,
(ULONG *) extra_parameters[0],
(ULONG *) extra_parameters[1],
(TX_THREAD **) extra_parameters[2],
@@ -1440,7 +1457,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -1539,7 +1556,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1564,7 +1581,7 @@ TX_QUEUE *queue_ptr;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* We need to get the max size of the buffer from the queue. */
@@ -1596,7 +1613,7 @@ TX_QUEUE *queue_ptr;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* We need to get the size of the message from the queue. */
@@ -1628,7 +1645,7 @@ VOID (*queue_send_notify)(TX_QUEUE *);
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* Since we need to write to the object, ensure it's valid. */
@@ -1672,7 +1689,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1687,7 +1704,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_SEMAPHORE_CREATE_CALL_NOT_USED
/* UINT _txe_semaphore_create(
TX_SEMAPHORE *semaphore_ptr, -> param_0
- CHAR *name_ptr, -> param_1
+ TX_NAME_CONST CHAR *name_ptr, -> param_1
ULONG initial_count, -> extra_parameters[0]
UINT semaphore_control_block_size -> extra_parameters[1]
); */
@@ -1710,7 +1727,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_semaphore_create(
(TX_SEMAPHORE *) param_0,
- (CHAR *) param_1,
+ (TX_NAME_CONST CHAR *) param_1,
(ULONG) extra_parameters[0],
(UINT) extra_parameters[1]
);
@@ -1729,7 +1746,10 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
+ return(TXM_MODULE_INVALID_MEMORY);
+
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_SEMAPHORE)))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1758,7 +1778,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1773,7 +1793,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_SEMAPHORE_INFO_GET_CALL_NOT_USED
/* UINT _txe_semaphore_info_get(
TX_SEMAPHORE *semaphore_ptr, -> param_0
- CHAR **name, -> param_1
+ TX_NAME_CONST CHAR **name, -> param_1
ULONG *current_value, -> extra_parameters[0]
TX_THREAD **first_suspended, -> extra_parameters[1]
ULONG *suspended_count, -> extra_parameters[2]
@@ -1786,7 +1806,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -1810,7 +1830,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_semaphore_info_get(
(TX_SEMAPHORE *) param_0,
- (CHAR **) param_1,
+ (TX_NAME_CONST CHAR **) param_1,
(ULONG *) extra_parameters[0],
(TX_THREAD **) extra_parameters[1],
(ULONG *) extra_parameters[2],
@@ -1835,7 +1855,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -1916,7 +1936,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1938,7 +1958,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1963,7 +1983,7 @@ VOID (*semaphore_put_notify)(TX_SEMAPHORE *);
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* Since we need to write to the object, ensure it's valid. */
@@ -1998,7 +2018,7 @@ VOID (*semaphore_put_notify)(TX_SEMAPHORE *);
#ifndef TXM_THREAD_CREATE_CALL_NOT_USED
/* UINT _txe_thread_create(
TX_THREAD *thread_ptr, -> param_0
- CHAR *name_ptr, -> param_1
+ TX_NAME_CONST CHAR *name_ptr, -> param_1
VOID (*entry_function)(ULONG entry_input), -> extra_parameters[0]
ULONG entry_input, -> extra_parameters[1]
VOID *stack_start, -> extra_parameters[2]
@@ -2037,7 +2057,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txm_module_manager_thread_create(
(TX_THREAD *) param_0,
- (CHAR *) param_1,
+ (TX_NAME_CONST CHAR *) param_1,
module_instance -> txm_module_instance_shell_entry_function,
(VOID (*)(ULONG entry_input)) extra_parameters[0],
(ULONG) extra_parameters[1],
@@ -2061,22 +2081,48 @@ ALIGN_TYPE return_value;
static ALIGN_TYPE _txm_module_manager_tx_thread_delete_dispatch(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE param_0)
{
-ALIGN_TYPE return_value;
+TX_THREAD *thread_ptr;
+ALIGN_TYPE return_value;
+ALIGN_TYPE stack_status;
+
+ thread_ptr = (TX_THREAD *) param_0;
+ stack_status = (ALIGN_TYPE) TX_SUCCESS;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
+ return(TXM_MODULE_INVALID_MEMORY);
+
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_THREAD)))
return(TXM_MODULE_INVALID_MEMORY);
}
- return_value = (ALIGN_TYPE) _txe_thread_delete(
- (TX_THREAD *) param_0
- );
+ return_value = (ALIGN_TYPE) _txe_thread_delete(thread_ptr);
- /* Deallocate object memory. */
+ /* Deallocate the kernel stack for a user-mode thread. The pointer is tested
+ rather than the module's properties: both thread create paths clear the whole
+ control block before filling it in, so a thread that carries no kernel stack
+ the manager allocated holds TX_NULL here, and a user-mode module can be given
+ the address of such a thread. */
+ if ((return_value == TX_SUCCESS) &&
+ (module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE) &&
+ (thread_ptr -> tx_thread_module_kernel_stack_start != TX_NULL))
+ {
+ stack_status = _txm_module_manager_object_deallocate(thread_ptr -> tx_thread_module_kernel_stack_start);
+ }
+
+ /* Deallocate thread object memory. This must be attempted even when the kernel
+ stack could not be released, otherwise a successful thread delete would leave
+ the thread object allocated forever. */
if (return_value == TX_SUCCESS)
{
- return_value = _txm_module_manager_object_deallocate((VOID *) param_0);
+ return_value = _txm_module_manager_object_deallocate((VOID *) thread_ptr);
+
+ /* Report the kernel stack failure if the thread object was released. */
+ if ((return_value == TX_SUCCESS) && (stack_status != TX_SUCCESS))
+ {
+ return_value = stack_status;
+ }
}
return(return_value);
}
@@ -2097,7 +2143,7 @@ VOID (*thread_entry_exit_notify)(TX_THREAD *, UINT);
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* Since we need to write to the object, ensure it's valid. */
@@ -2148,7 +2194,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_THREAD_INFO_GET_CALL_NOT_USED
/* UINT _txe_thread_info_get(
TX_THREAD *thread_ptr, -> param_0
- CHAR **name, -> param_1
+ TX_NAME_CONST CHAR **name, -> param_1
UINT *state, -> extra_parameters[0]
ULONG *run_count, -> extra_parameters[1]
UINT *priority, -> extra_parameters[2]
@@ -2164,7 +2210,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -2197,7 +2243,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_thread_info_get(
(TX_THREAD *) param_0,
- (CHAR **) param_1,
+ (TX_NAME_CONST CHAR **) param_1,
(UINT *) extra_parameters[0],
(ULONG *) extra_parameters[1],
(UINT *) extra_parameters[2],
@@ -2250,7 +2296,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -2397,7 +2443,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_2, sizeof(UINT)))
@@ -2431,7 +2477,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_2, sizeof(UINT)))
@@ -2468,7 +2514,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2490,7 +2536,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2547,7 +2593,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2576,7 +2622,7 @@ TX_THREAD *thread_ptr;
{
return(TXM_MODULE_INVALID_MEMORY);
}
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2626,7 +2672,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2650,7 +2696,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_2, sizeof(ULONG)))
@@ -2677,7 +2723,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2725,7 +2771,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2749,7 +2795,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2765,7 +2811,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_TIMER_CREATE_CALL_NOT_USED
/* UINT _txe_timer_create(
TX_TIMER *timer_ptr, -> param_0
- CHAR *name_ptr, -> param_1
+ TX_NAME_CONST CHAR *name_ptr, -> param_1
VOID (*expiration_function)(ULONG), -> extra_parameters[0]
ULONG expiration_input, -> extra_parameters[1]
ULONG initial_ticks, -> extra_parameters[2]
@@ -2808,7 +2854,7 @@ VOID (*expiration_function)(ULONG);
return_value = (ALIGN_TYPE) _txe_timer_create(
(TX_TIMER *) param_0,
- (CHAR *) param_1,
+ (TX_NAME_CONST CHAR *) param_1,
(VOID (*)(ULONG)) expiration_function,
(ULONG) extra_parameters[1],
(ULONG) extra_parameters[2],
@@ -2846,7 +2892,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2868,7 +2914,10 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
+ return(TXM_MODULE_INVALID_MEMORY);
+
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_TIMER)))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2888,7 +2937,7 @@ ALIGN_TYPE return_value;
#ifndef TXM_TIMER_INFO_GET_CALL_NOT_USED
/* UINT _txe_timer_info_get(
TX_TIMER *timer_ptr, -> param_0
- CHAR **name, -> param_1
+ TX_NAME_CONST CHAR **name, -> param_1
UINT *active, -> extra_parameters[0]
ULONG *remaining_ticks, -> extra_parameters[1]
ULONG *reschedule_ticks, -> extra_parameters[2]
@@ -2901,7 +2950,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -2925,7 +2974,7 @@ ALIGN_TYPE return_value;
return_value = (ALIGN_TYPE) _txe_timer_info_get(
(TX_TIMER *) param_0,
- (CHAR **) param_1,
+ (TX_NAME_CONST CHAR **) param_1,
(UINT *) extra_parameters[0],
(ULONG *) extra_parameters[1],
(ULONG *) extra_parameters[2],
@@ -2951,7 +3000,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -3232,41 +3281,6 @@ static ALIGN_TYPE _txm_module_manager_txm_module_object_deallocate_dispatch(TXM_
{
ALIGN_TYPE return_value;
-TXM_MODULE_ALLOCATED_OBJECT *object_ptr;
-ALIGN_TYPE object_end;
-ALIGN_TYPE object_pool_end;
-
- if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
- {
- /* Is the object pool created? */
- if (_txm_module_manager_object_pool_created == TX_TRUE)
- {
-
- /* Get the module allocated object. */
- object_ptr = ((TXM_MODULE_ALLOCATED_OBJECT *) param_0) - 1;
-
- /* Get the end address of the object pool. */
- object_pool_end = (ALIGN_TYPE) (_txm_module_manager_object_pool.tx_byte_pool_start + _txm_module_manager_object_pool.tx_byte_pool_size);
-
- /* Check that the pointer is in the object pool. */
- if ((ALIGN_TYPE) object_ptr < (ALIGN_TYPE) _txm_module_manager_object_pool.tx_byte_pool_start ||
- (ALIGN_TYPE) object_ptr >= (ALIGN_TYPE) object_pool_end)
- {
- /* Pointer is outside of the object pool. */
- return(TXM_MODULE_INVALID_MEMORY);
- }
-
- /* Get the end addresses of the object. */
- object_end = ((ALIGN_TYPE) object_ptr) + sizeof(TXM_MODULE_ALLOCATED_OBJECT) + object_ptr -> txm_module_object_size;
-
- /* Check that the object is in the object pool. */
- if (object_end >= object_pool_end)
- {
- /* Object is outside of the object pool. */
- return(TXM_MODULE_INVALID_MEMORY);
- }
- }
- }
return_value = (ALIGN_TYPE) _txm_module_manager_object_deallocate(
(VOID *) param_0
@@ -3288,11 +3302,10 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING(module_instance, param_1))
- return(TXM_MODULE_INVALID_MEMORY);
-
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_2, sizeof(VOID *)))
- return(TXM_MODULE_INVALID_MEMORY);
+ /* This service carries no name length, so the manager searches with the largest
+ length a UINT can hold and no readable range can be proven for the name. A
+ memory-protected module must use the extended service, which declares one. */
+ return(TXM_MODULE_INVALID_MEMORY);
}
return_value = (ALIGN_TYPE) _txm_module_manager_object_pointer_get(
@@ -3318,10 +3331,13 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING(module_instance, param_1))
+ if (!TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, (ALIGN_TYPE)extra_parameters, sizeof(ALIGN_TYPE[2])))
return(TXM_MODULE_INVALID_MEMORY);
- if (!TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, (ALIGN_TYPE)extra_parameters, sizeof(ALIGN_TYPE[2])))
+ /* The name length has to be checked before it is trusted, so the extra parameter
+ array is checked first. The comparison reads the declared length plus the
+ terminator that follows it, and all of that must be inside the module. */
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING_RANGE(module_instance, param_1, (UINT) extra_parameters[0]))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, extra_parameters[1], sizeof(VOID *)))
diff --git a/common_modules/module_manager/inc/txm_module_manager_util.h b/common_modules/module_manager/inc/txm_module_manager_util.h
index 45c7f409..3583edcc 100644
--- a/common_modules/module_manager/inc/txm_module_manager_util.h
+++ b/common_modules/module_manager/inc/txm_module_manager_util.h
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -43,8 +45,32 @@
/* Define check macros for modules. */
+/* A port supplies TXM_MODULE_MANAGER_CHECK_INSIDE_DATA to decide whether a caller-supplied
+ range lies inside the module's writable data or shared memory. Ports whose check can tell
+ a read-only region from a writable one also supply the two intent-specific variants below.
+ Ports that cannot make the distinction inherit their single check for both intents, so
+ their behaviour is unchanged. */
+
+#ifndef TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ
+#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size) \
+ TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size)
+#endif
+
+#ifndef TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE
+#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size) \
+ TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size)
+#endif
+
+/* A range is outside the module's data only when no part of it is reachable by the module.
+ The read intent is used here because it describes the widest set of reachable addresses.
+ A port whose inside check cannot prove the whole range at once must supply its own
+ definition, because negating a partial-range check would report a partly reachable range
+ as being outside the module. */
+
+#ifndef TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA
#define TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA(module_instance, obj_ptr, obj_size) \
- (!(TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size)))
+ (!(TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size)))
+#endif
#define TXM_MODULE_MANAGER_CHECK_INSIDE_CODE(module_instance, obj_ptr, obj_size) \
(((obj_ptr) < ((obj_ptr) + (obj_size))) && \
@@ -63,12 +89,14 @@
/* Define macros for module. */
+/* The module reads from these ranges, so a read-only region is acceptable. */
#define TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, obj_ptr, obj_size) \
- (TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) || \
+ (TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size) || \
TXM_MODULE_MANAGER_CHECK_INSIDE_CODE(module_instance, obj_ptr, obj_size))
+/* The kernel writes to these ranges, so the module must be able to write them too. */
#define TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, obj_ptr, obj_size) \
- TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size)
+ TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size)
#define TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, obj_ptr, obj_size) \
(TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA(module_instance, obj_ptr, obj_size) && \
@@ -89,19 +117,59 @@
((TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, buffer_ptr, buffer_size)) || \
((void *) (buffer_ptr) == TX_NULL))
-/* Kernel objects should be outside the module at the very least. */
+/* Kernel objects a module names must be authenticated before a privileged service is
+ allowed to dereference them. Being outside the module is necessary but nowhere near
+ sufficient: the manager's object pool is outside every module, so an address shifted
+ into the interior of one of the module's own privileged allocations satisfies that
+ test while denoting no object at all. Authentication answers the question the
+ location test cannot -- is this the exact address of a live kernel object of the type
+ this service expects -- and it answers it from manager and kernel bookkeeping rather
+ than from fields of the purported object, which a module can influence.
+
+ TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE is the complete check and is what
+ the dispatch table uses. It is given the object type rather than a control block size
+ so that it can also establish the type, which a size cannot: distinct object types of
+ equal size exist.
+
+ TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE is retained for dispatchers outside this
+ repository that pass a size. It authenticates addresses in the manager's object pool,
+ which is what the shifted-pointer attack needs, but without a type it can neither
+ establish the type nor authenticate an application-owned object, so in-repository code
+ should use the typed form. */
#define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, obj_ptr, obj_size) \
(_txm_module_manager_param_check_object_for_use(module_instance, obj_ptr, obj_size))
+#define TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, obj_ptr, obj_type) \
+ (_txm_module_manager_param_check_typed_object_for_use(module_instance, obj_ptr, obj_type))
+
/* When creating an object, the object must be inside the object pool. */
#define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_CREATION(module_instance, obj_ptr, obj_size) \
(_txm_module_manager_param_check_object_for_creation(module_instance, obj_ptr, obj_size))
+/* When deleting an object, being allowed to use it is not enough. Deletion is the
+ inverse of creation, so it asks what creation asks: that the object is one this
+ module allocated from the manager's object pool, at the exact address the manager
+ gave it, for an object of this size. A module may hold a pointer to an object it
+ does not own -- the manager's object lookup service hands application-owned
+ objects to modules by name, and sharing an object is what that service is for --
+ and this is what separates using such an object from destroying it. */
+#define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, obj_ptr, obj_size) \
+ (_txm_module_manager_allocated_object_check(module_instance, obj_ptr, obj_size))
+
/* Strings we dereference can be in RW/RO/Shared areas. */
#define TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING(module_instance, string_ptr) \
((TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, string_ptr, 1)) || \
((void *) (string_ptr) == TX_NULL))
+/* Strings we walk are checked over the whole range the walk may reach: the declared
+ length plus the terminating character that follows it, since a length excludes the
+ terminator and the comparison reads it. A length whose range cannot be expressed
+ is refused rather than truncated. */
+#define TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING_RANGE(module_instance, string_ptr, string_length) \
+ (((((ALIGN_TYPE) (string_length)) < (~((ALIGN_TYPE) 0))) && \
+ (TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, string_ptr, ((ALIGN_TYPE) (string_length)) + ((ALIGN_TYPE) 1)))) || \
+ ((void *) (string_ptr) == TX_NULL))
+
#define TXM_MODULE_MANAGER_UTIL_MAX_VALUE_OF_TYPE_UNSIGNED(type) ((1ULL << (sizeof(type) * 8)) - 1)
#define TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(augend, addend, result) \
@@ -118,10 +186,18 @@
UINT _txm_module_manager_object_memory_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size);
UINT _txm_module_manager_object_size_check(ALIGN_TYPE object_ptr, ULONG object_size);
-UINT _txm_module_manager_object_name_compare(CHAR *object_name1, UINT object_name1_length, CHAR *object_name2);
+UINT _txm_module_manager_object_name_compare(CHAR *object_name1, UINT object_name1_length, TX_NAME_CONST CHAR *object_name2);
UCHAR _txm_module_manager_created_object_check(TXM_MODULE_INSTANCE *module_instance, void *object_ptr);
UINT _txm_module_manager_param_check_object_for_creation(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size);
UINT _txm_module_manager_param_check_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size);
+UINT _txm_module_manager_param_check_typed_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, UINT object_type);
+UINT _txm_module_manager_allocated_object_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size);
+TXM_MODULE_ALLOCATED_OBJECT
+ *_txm_module_manager_allocated_object_find(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG *object_size_ptr);
+UINT _txm_module_manager_object_type_size_get(UINT object_type, ULONG *object_size);
+UINT _txm_module_manager_created_object_type_check(ALIGN_TYPE object_ptr, UINT object_type);
+UINT _txm_module_manager_object_id_check(ALIGN_TYPE object_ptr, UINT object_type);
+UINT _txm_module_manager_live_object_check(ALIGN_TYPE object_ptr);
UINT _txm_module_manager_util_code_allocation_size_and_alignment_get(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_alignment_dest, ULONG *code_allocation_size_dest);
#endif
diff --git a/common_modules/module_manager/src/txm_module_manager_absolute_load.c b/common_modules/module_manager/src/txm_module_manager_absolute_load.c
index dee6efd2..3fc06000 100644
--- a/common_modules/module_manager/src/txm_module_manager_absolute_load.c
+++ b/common_modules/module_manager/src/txm_module_manager_absolute_load.c
@@ -1,6 +1,6 @@
/***************************************************************************
* Copyright (c) 2024 Microsoft Corporation
- * Copyright (c) 2026-present Eclipse ThreadX contributors
+ * Copyright (c) 2026 Eclipse ThreadX contributors
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -23,29 +25,57 @@
#define TX_SOURCE_CODE
#include "tx_api.h"
-#include "tx_initialize.h"
-#include "tx_mutex.h"
-#include "tx_thread.h"
-#include "tx_byte_pool.h"
#include "txm_module.h"
-#include "txm_module_manager_util.h"
+#ifndef TXM_MODULE_MANAGER_ABSOLUTE_LOAD_CALL_NOT_USED
+
+/* DEPRECATION NOTICE
+ * txm_module_manager_absolute_load() is deprecated. Do not use it in new code.
+ *
+ * WHY: an absolutely located module has its code and its data placed at two
+ * independent fixed addresses by the module's linker script. This service
+ * receives only the code address, and the module preamble carries the code and
+ * data sizes but not the data address. The module manager therefore has no way
+ * to determine where the module's data area is, and cannot describe it in the
+ * module instance. The affected fields are left empty by this wrapper.
+ *
+ * WHAT TO DO: replace calls with txm_module_manager_absolute_load_extended(),
+ * passing the module's data area address as the fourth argument. That address
+ * is the RAM segment start defined in the module's linker script.
+ *
+ * RISK: with the data area unknown, the module manager cannot tell whether an
+ * object, a thread control block, or the trace buffer resides in the module's
+ * data area, and a memory protection unit cannot be programmed to cover it.
+ * Modules that request memory protection are therefore rejected with
+ * TXM_MODULE_INVALID_PROPERTIES.
+ *
+ * Define TXM_MODULE_MANAGER_ABSOLUTE_LOAD_CALL_NOT_USED to remove this service
+ * and this message from the build.
+ */
+#pragma message("txm_module_manager_absolute_load() is deprecated. " \
+ "Use txm_module_manager_absolute_load_extended() and pass " \
+ "the module's data area address.")
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_absolute_load PORTABLE C */
-/* 6.1.3 */
+/* 6.5.2 */
/* AUTHOR */
/* */
/* Andres Mlinar, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
-/* This function ensures the code-related and data-related parts of */
-/* the module preamble are valid and prepares the module for */
-/* execution. */
+/* DEPRECATED. Use _txm_module_manager_absolute_load_extended() */
+/* instead, passing the module's data area address. This wrapper */
+/* passes TX_NULL, which leaves the module instance's data area */
+/* description empty because the module manager cannot derive the */
+/* data area address of an absolutely located module. Modules that */
+/* request memory protection are rejected with */
+/* TXM_MODULE_INVALID_PROPERTIES, because the memory protection */
+/* hardware cannot be programmed to cover an unknown data area. */
/* */
/* INPUT */
/* */
@@ -59,9 +89,8 @@
/* */
/* CALLS */
/* */
-/* _tx_byte_allocate Allocate data area */
-/* _tx_mutex_get Get protection mutex */
-/* _tx_mutex_put Release protection mutex */
+/* _txm_module_manager_absolute_load_extended */
+/* Load the module */
/* */
/* CALLED BY */
/* */
@@ -71,363 +100,13 @@
UINT _txm_module_manager_absolute_load(TXM_MODULE_INSTANCE *module_instance, CHAR *module_name, VOID *module_location)
{
-TX_INTERRUPT_SAVE_AREA
-
-TXM_MODULE_PREAMBLE *module_preamble;
-ULONG code_size;
-ULONG code_alignment;
-ULONG code_allocation_size_ignored;
-UINT status;
-
-TXM_MODULE_INSTANCE *next_module, *previous_module;
-ULONG start_stop_stack_size;
-ULONG callback_stack_size;
-ULONG code_size_ignored;
-ULONG code_alignment_ignored;
-ALIGN_TYPE data_start;
-ULONG data_size;
-ULONG data_alignment;
-ULONG data_allocation_size;
-ULONG module_properties;
-CHAR *memory_ptr;
-
-
- /* Check for interrupt call. */
- if (TX_THREAD_GET_SYSTEM_STATE() != 0)
- {
-
- /* Now, make sure the call is from an interrupt and not initialization. */
- if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
- {
-
- /* Invalid caller of this function, return appropriate error code. */
- return(TX_CALLER_ERROR);
- }
- }
-
- /* Determine if the module manager has not been initialized yet. */
- if (_txm_module_manager_ready != TX_TRUE)
- {
-
- /* Module manager has not been initialized. */
- return(TX_NOT_AVAILABLE);
- }
-
- /* Determine if the module is valid. */
- if (module_instance == TX_NULL)
- {
-
- /* Invalid module pointer. */
- return(TX_PTR_ERROR);
- }
-
- /* Get module manager protection mutex. */
- _tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
-
- /* Determine if the module is already valid. */
- if (module_instance -> txm_module_instance_id == TXM_MODULE_ID)
- {
-
- /* Release the protection mutex. */
- _tx_mutex_put(&_txm_module_manager_mutex);
-
- /* Module already loaded. */
- return(TXM_MODULE_ALREADY_LOADED);
- }
-
- /* Pickup the module's information. */
- module_preamble = (TXM_MODULE_PREAMBLE *) module_location;
-
- /* Check to make sure there is a valid module to load. */
- if (module_preamble -> txm_module_preamble_id != TXM_MODULE_ID)
- {
-
- /* Release the protection mutex. */
- _tx_mutex_put(&_txm_module_manager_mutex);
-
- /* Invalid module preamble. */
- return(TXM_MODULE_INVALID);
- }
-
- /* Check the properties of this module. */
- module_properties = module_preamble -> txm_module_preamble_property_flags & TXM_MODULE_OPTIONS_MASK;
- if (/* Ensure the requested properties are supported. */
- ((module_properties & _txm_module_manager_properties_supported) != module_properties) ||
- /* Ensure the required properties are there. */
- ((_txm_module_manager_properties_required & module_properties) != _txm_module_manager_properties_required) ||
- /* If memory protection is enabled, then so must user mode. */
- ((module_properties & TXM_MODULE_MEMORY_PROTECTION) && !(module_properties & TXM_MODULE_USER_MODE))
- )
- {
-
- /* Release the protection mutex. */
- _tx_mutex_put(&_txm_module_manager_mutex);
-
- /* Invalid properties. Return error. */
- return(TXM_MODULE_INVALID_PROPERTIES);
- }
-
- /* Check for valid module entry offsets. */
- if ((module_preamble -> txm_module_preamble_shell_entry_function == 0) ||
- (module_preamble -> txm_module_preamble_start_function == 0))
- {
-
- /* Release the protection mutex. */
- _tx_mutex_put(&_txm_module_manager_mutex);
-
- /* Invalid module preamble. */
- return(TXM_MODULE_INVALID);
- }
-
- /* Check for valid sizes. */
- if ((module_preamble -> txm_module_preamble_code_size == 0) ||
- /* (module_preamble -> txm_module_preamble_data_size == 0) || *** a zero data size is valid */
- (module_preamble -> txm_module_preamble_start_stop_stack_size == 0) ||
- (module_preamble -> txm_module_preamble_callback_stack_size == 0))
- {
-
- /* Release the protection mutex. */
- _tx_mutex_put(&_txm_module_manager_mutex);
-
- /* Invalid module preamble. */
- return(TXM_MODULE_INVALID);
- }
-
- /* Get the amount of the bytes we need to allocate for the module's code
- as well as the required alignment. Note that because this is an absolute
- load, we only want the code alignment so we can check it. */
- status = _txm_module_manager_util_code_allocation_size_and_alignment_get(module_preamble, &code_alignment, &code_allocation_size_ignored);
- if (status != TX_SUCCESS)
- {
-
- /* Math overflow error occurred. */
- return(status);
- }
-
- /* Since this is an absolute load, check the alignment of the module's instruction area (code). */
- TXM_MODULE_MANAGER_CHECK_CODE_ALIGNMENT(module_location, code_alignment)
-
- /* Initialize module control block to all zeros. */
- TX_MEMSET(module_instance, 0, sizeof(TXM_MODULE_INSTANCE));
-
- /* Pickup the basic module sizes. */
- code_size = module_preamble -> txm_module_preamble_code_size;
- data_size = module_preamble -> txm_module_preamble_data_size;
- start_stop_stack_size = module_preamble -> txm_module_preamble_start_stop_stack_size;
- callback_stack_size = module_preamble -> txm_module_preamble_callback_stack_size;
-
- TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_size, TXM_MODULE_DATA_ALIGNMENT, data_size);
- data_size = ((data_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
-
- /* Adjust the size of the module elements to be aligned to the default alignment. We do this
- so that when we partition the allocated memory, we can simply place these regions right beside
- each other without having to align their pointers. Note this only works when they all have
- the same alignment. */
-
- TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(start_stop_stack_size, TXM_MODULE_DATA_ALIGNMENT, start_stop_stack_size);
- start_stop_stack_size = ((start_stop_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
-
- TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(callback_stack_size, TXM_MODULE_DATA_ALIGNMENT, callback_stack_size);
- callback_stack_size = ((callback_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
-
- /* Update the data size to account for the default thread stacks. */
- data_allocation_size = 0;
- TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, start_stop_stack_size, data_allocation_size);
- TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, callback_stack_size, data_allocation_size);
-
- /* Setup the default code and data alignments. */
- data_alignment = (ULONG) TXM_MODULE_DATA_ALIGNMENT;
-
- /* Get the port-specific alignment for the data size. Note we only want data
- so we pass values of 1 for code (to avoid any possible div by 0 errors). */
- code_size_ignored = 1;
- code_alignment_ignored = 1;
- TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size_ignored, code_alignment_ignored, data_allocation_size, data_alignment)
-
- /* Calculate the module's total RAM memory requirement. This entire area is allocated from the module
- manager's byte pool. The general layout is defined as follows:
-
- Lowest Address: Start of start/stop thread stack
- ... [note: thread entry info is embedded near end of stack areas]
- End of start/stop thread stack
+UINT status;
- Start of callback thread stack
- ... [note: thread entry info is embedded near end of stack areas]
- End of callback thread stack
- Highest Address: */
+ /* Call the extended service with an unknown data area location. */
+ status = _txm_module_manager_absolute_load_extended(module_instance, module_name, module_location, TX_NULL);
- /* Add an extra alignment increment so we can align the pointer after allocation. */
- TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, data_alignment, data_allocation_size);
-
- /* Allocate memory for the module. */
- status = _tx_byte_allocate(&_txm_module_manager_byte_pool, (VOID **) &memory_ptr, data_allocation_size, TX_NO_WAIT);
-
- /* Determine if the module memory allocation was successful. */
- if (status)
- {
-
- /* Release the protection mutex. */
- _tx_mutex_put(&_txm_module_manager_mutex);
-
- /* No memory, return an error. */
- return(TX_NO_MEMORY);
- }
-
- /* Clear the allocated memory. */
- TX_MEMSET(memory_ptr, ((UCHAR) 0), data_allocation_size);
-
- /* Disable interrupts. */
- TX_DISABLE
-
- /* Setup the module instance structure. */
- module_instance -> txm_module_instance_id = TXM_MODULE_ID;
-
- /* Save the module name. */
- module_instance -> txm_module_instance_name = module_name;
-
- /* Save the module properties. */
- module_instance -> txm_module_instance_property_flags = module_preamble -> txm_module_preamble_property_flags;
-
- /* Set the module data memory allocation. This is the address released
- when the module is unloaded. */
- module_instance -> txm_module_instance_data_allocation_ptr = (VOID *) memory_ptr;
-
- /* Save the data allocation size. */
- module_instance -> txm_module_instance_data_allocation_size = data_allocation_size;
-
- /* Calculate the actual start of the data area. This needs to be adjusted based on the alignment. */
- data_start = (ALIGN_TYPE) memory_ptr;
- data_start = (data_start + (((ALIGN_TYPE)data_alignment) - 1)) & ~(((ALIGN_TYPE)data_alignment) - 1);
- memory_ptr = (CHAR *) data_start;
-
- /* Compute the beginning and end of the data area. */
-#ifdef ALIGN_TYPE_DEFINED
- module_instance -> txm_module_instance_data_start = (VOID *) (((CHAR *) (ALIGN_TYPE) module_preamble->txm_module_preamble_code_size) + sizeof(TXM_MODULE_PREAMBLE));
- module_instance -> txm_module_instance_data_end = (VOID *) (((CHAR *) (ALIGN_TYPE) module_instance -> txm_module_instance_data_start) + module_preamble->txm_module_preamble_data_size);
-#else
- module_instance -> txm_module_instance_data_start = (VOID *) (((CHAR *) module_preamble->txm_module_preamble_code_size) + sizeof(TXM_MODULE_PREAMBLE));
- module_instance -> txm_module_instance_data_end = (VOID *) (((CHAR *) module_instance -> txm_module_instance_data_start) + module_preamble->txm_module_preamble_data_size);
-#endif
-
- /* Save the size of the data area. */
- module_instance -> txm_module_instance_data_size = data_size;
-
- /* Set the module code memory allocation. This is the address released
- when the module is unloaded. */
- module_instance -> txm_module_instance_code_allocation_ptr = (VOID *) NULL;
-
- /* Save the code allocation size. */
- module_instance -> txm_module_instance_code_allocation_size = 0;
-
- /* Setup the code pointers. Since the code was loaded in-place, this is effectively just the values supplied in the API call. */
- module_instance -> txm_module_instance_code_start = (VOID *) module_location;
- module_instance -> txm_module_instance_code_end = (VOID *) (((CHAR *) module_location) + (code_size - 1));
-
- /* Setup the code size. */
- module_instance -> txm_module_instance_code_size = code_size;
-
- /* Save the module's total memory usage. */
- module_instance -> txm_module_instance_total_ram_usage = 0 /* Code is executed in place */ + data_allocation_size /* just the size of stacks */;
-
- /* Set the module state to started. */
- module_instance -> txm_module_instance_state = TXM_MODULE_LOADED;
-
- /* Save the preamble pointer. */
- module_instance -> txm_module_instance_preamble_ptr = module_preamble;
-
- /* Save the module application ID in the module instance. */
- module_instance -> txm_module_instance_application_module_id = module_preamble -> txm_module_preamble_application_module_id;
-
- /* Setup the module's start/stop thread stack area. */
- module_instance -> txm_module_instance_start_stop_stack_start_address = (VOID *) (memory_ptr);
- module_instance -> txm_module_instance_start_stop_stack_size = start_stop_stack_size;
- module_instance -> txm_module_instance_start_stop_stack_end_address = (VOID *) (memory_ptr + (start_stop_stack_size - 1));
-
- /* Move the memory pointer forward. */
- memory_ptr = memory_ptr + start_stop_stack_size;
-
- /* Save the start/stop thread priority. */
- module_instance -> txm_module_instance_start_stop_priority = module_preamble -> txm_module_preamble_start_stop_priority;
-
- /* Setup the module's callback thread stack area. */
- module_instance -> txm_module_instance_callback_stack_start_address = (VOID *) (memory_ptr);
- module_instance -> txm_module_instance_callback_stack_size = callback_stack_size;
- module_instance -> txm_module_instance_callback_stack_end_address = (VOID *) (memory_ptr + (callback_stack_size - 1));
-
- /* Move the memory pointer forward. */
- memory_ptr = memory_ptr + callback_stack_size;
-
- /* Save the callback thread priority. */
- module_instance -> txm_module_instance_callback_priority = module_preamble -> txm_module_preamble_callback_priority;
-
- /* Setup the start of the module data section. */
- module_instance -> txm_module_instance_module_data_base_address = (VOID *) (memory_ptr);
-
- /* Build actual addresses based on load... Setup all the function pointers. Any adjustments needed to shell entry, start function, and callback function are defined in the
- module preamble. */
-#ifdef ALIGN_TYPE_DEFINED
- module_instance -> txm_module_instance_shell_entry_function = (VOID (*)(TX_THREAD *, TXM_MODULE_INSTANCE *)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_shell_entry_function);
- module_instance -> txm_module_instance_start_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_start_function);
- module_instance -> txm_module_instance_callback_request_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_callback_function);
-#else
- module_instance -> txm_module_instance_shell_entry_function = (VOID (*)(TX_THREAD *, TXM_MODULE_INSTANCE *)) ((VOID *) module_preamble -> txm_module_preamble_shell_entry_function);
- module_instance -> txm_module_instance_start_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_start_function);
- module_instance -> txm_module_instance_callback_request_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_callback_function);
-#endif
-
- /* Determine if there is a stop function for this module. */
- if (module_preamble -> txm_module_preamble_stop_function)
- {
-
- /* Yes, there is a stop function, build the address. */
-#ifdef ALIGN_TYPE_DEFINED
- module_instance -> txm_module_instance_stop_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_stop_function);
-#else
- module_instance -> txm_module_instance_stop_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_stop_function);
-#endif
- }
- else
- {
-
- /* No, there is no stop function. Just set the pointer to NULL. */
- module_instance -> txm_module_instance_stop_thread_entry = TX_NULL;
- }
-
- /* Load the module control block with port-specific information. */
- TXM_MODULE_MANAGER_MODULE_SETUP(module_instance);
-
- /* Now add the module to the linked list of created modules. */
- if (_txm_module_manger_loaded_count++ == 0)
- {
-
- /* The loaded module list is empty. Add module to empty list. */
- _txm_module_manager_loaded_list_ptr = module_instance;
- module_instance -> txm_module_instance_loaded_next = module_instance;
- module_instance -> txm_module_instance_loaded_previous = module_instance;
- }
- else
- {
-
- /* This list is not NULL, add to the end of the list. */
- next_module = _txm_module_manager_loaded_list_ptr;
- previous_module = next_module -> txm_module_instance_loaded_previous;
-
- /* Place the new module in the list. */
- next_module -> txm_module_instance_loaded_previous = module_instance;
- previous_module -> txm_module_instance_loaded_next = module_instance;
-
- /* Setup this module's created links. */
- module_instance -> txm_module_instance_loaded_previous = previous_module;
- module_instance -> txm_module_instance_loaded_next = next_module;
- }
-
- /* Restore interrupts. */
- TX_RESTORE
-
- /* Release the protection mutex. */
- _tx_mutex_put(&_txm_module_manager_mutex);
-
- /* Return success. */
- return(TX_SUCCESS);
+ /* Return completion status. */
+ return(status);
}
+#endif
diff --git a/common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c b/common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c
new file mode 100644
index 00000000..874cd1d6
--- /dev/null
+++ b/common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c
@@ -0,0 +1,486 @@
+/***************************************************************************
+ * Copyright (c) 2024 Microsoft Corporation
+ * Copyright (c) 2026-present Eclipse ThreadX contributors
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the MIT License which is available at
+ * https://opensource.org/licenses/MIT.
+ *
+ * SPDX-License-Identifier: MIT
+ **************************************************************************/
+
+// Portions of this file were generated with AI assistance.
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Module Manager */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_mutex.h"
+#include "tx_thread.h"
+#include "tx_byte_pool.h"
+#include "txm_module.h"
+#include "txm_module_manager_util.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_absolute_load_extended PORTABLE C */
+/* 6.5.2 */
+/* AUTHOR */
+/* */
+/* Andres Mlinar, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function ensures the code-related and data-related parts of */
+/* the module preamble are valid and prepares the module for */
+/* execution. */
+/* */
+/* An absolutely located module has its code and its data placed at */
+/* fixed addresses by the module's linker script. The module preamble */
+/* carries only the code and data sizes, so the module manager cannot */
+/* derive the module's data location on its own. This service accepts */
+/* that address from the caller, which allows the module instance's */
+/* data area to be described correctly. */
+/* */
+/* INPUT */
+/* */
+/* module_instance Module instance pointer */
+/* module_name Module name pointer */
+/* module_location Module code location */
+/* module_data_location Module data location, or TX_NULL */
+/* when the data location is not */
+/* known to the caller. Memory */
+/* protection cannot be used when */
+/* it is TX_NULL. */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_byte_allocate Allocate data area */
+/* _tx_mutex_get Get protection mutex */
+/* _tx_mutex_put Release protection mutex */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* _txm_module_manager_absolute_load Deprecated wrapper */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_absolute_load_extended(TXM_MODULE_INSTANCE *module_instance, CHAR *module_name, VOID *module_location, VOID *module_data_location)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TXM_MODULE_PREAMBLE *module_preamble;
+ULONG code_size;
+ULONG code_alignment;
+ULONG code_allocation_size_ignored;
+UINT status;
+
+TXM_MODULE_INSTANCE *next_module, *previous_module;
+ULONG start_stop_stack_size;
+ULONG callback_stack_size;
+ULONG code_size_ignored;
+ULONG code_alignment_ignored;
+ALIGN_TYPE data_start;
+ULONG data_size;
+ULONG data_alignment;
+ULONG data_allocation_size;
+ULONG module_properties;
+CHAR *memory_ptr;
+
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != 0)
+ {
+
+ /* Now, make sure the call is from an interrupt and not initialization. */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+
+ /* Invalid caller of this function, return appropriate error code. */
+ return(TX_CALLER_ERROR);
+ }
+ }
+
+ /* Determine if the module manager has not been initialized yet. */
+ if (_txm_module_manager_ready != TX_TRUE)
+ {
+
+ /* Module manager has not been initialized. */
+ return(TX_NOT_AVAILABLE);
+ }
+
+ /* Determine if the module is valid. */
+ if (module_instance == TX_NULL)
+ {
+
+ /* Invalid module pointer. */
+ return(TX_PTR_ERROR);
+ }
+
+ /* Get module manager protection mutex. */
+ _tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
+
+ /* Determine if the module is already valid. */
+ if (module_instance -> txm_module_instance_id == TXM_MODULE_ID)
+ {
+
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Module already loaded. */
+ return(TXM_MODULE_ALREADY_LOADED);
+ }
+
+ /* Pickup the module's information. */
+ module_preamble = (TXM_MODULE_PREAMBLE *) module_location;
+
+ /* Check to make sure there is a valid module to load. */
+ if (module_preamble -> txm_module_preamble_id != TXM_MODULE_ID)
+ {
+
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Invalid module preamble. */
+ return(TXM_MODULE_INVALID);
+ }
+
+ /* Check the properties of this module. */
+ module_properties = module_preamble -> txm_module_preamble_property_flags & TXM_MODULE_OPTIONS_MASK;
+ if (/* Ensure the requested properties are supported. */
+ ((module_properties & _txm_module_manager_properties_supported) != module_properties) ||
+ /* Ensure the required properties are there. */
+ ((_txm_module_manager_properties_required & module_properties) != _txm_module_manager_properties_required) ||
+ /* If memory protection is enabled, then so must user mode. */
+ ((module_properties & TXM_MODULE_MEMORY_PROTECTION) && !(module_properties & TXM_MODULE_USER_MODE)) ||
+ /* Memory protection requires a known data area, since the memory protection hardware must
+ be programmed to cover it. */
+ ((module_properties & TXM_MODULE_MEMORY_PROTECTION) && (module_data_location == TX_NULL))
+ )
+ {
+
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Invalid properties. Return error. */
+ return(TXM_MODULE_INVALID_PROPERTIES);
+ }
+
+ /* Check for valid module entry offsets. */
+ if ((module_preamble -> txm_module_preamble_shell_entry_function == 0) ||
+ (module_preamble -> txm_module_preamble_start_function == 0))
+ {
+
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Invalid module preamble. */
+ return(TXM_MODULE_INVALID);
+ }
+
+ /* Check for valid sizes. */
+ if ((module_preamble -> txm_module_preamble_code_size == 0) ||
+ /* (module_preamble -> txm_module_preamble_data_size == 0) || *** a zero data size is valid */
+ (module_preamble -> txm_module_preamble_start_stop_stack_size == 0) ||
+ (module_preamble -> txm_module_preamble_callback_stack_size == 0))
+ {
+
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Invalid module preamble. */
+ return(TXM_MODULE_INVALID);
+ }
+
+ /* Get the amount of the bytes we need to allocate for the module's code
+ as well as the required alignment. Note that because this is an absolute
+ load, we only want the code alignment so we can check it. */
+ status = _txm_module_manager_util_code_allocation_size_and_alignment_get(module_preamble, &code_alignment, &code_allocation_size_ignored);
+ if (status != TX_SUCCESS)
+ {
+
+ /* Math overflow error occurred. */
+ return(status);
+ }
+
+ /* Since this is an absolute load, check the alignment of the module's instruction area (code). */
+ TXM_MODULE_MANAGER_CHECK_CODE_ALIGNMENT(module_location, code_alignment)
+
+ /* Initialize module control block to all zeros. */
+ TX_MEMSET(module_instance, 0, sizeof(TXM_MODULE_INSTANCE));
+
+ /* Pickup the basic module sizes. */
+ code_size = module_preamble -> txm_module_preamble_code_size;
+ data_size = module_preamble -> txm_module_preamble_data_size;
+ start_stop_stack_size = module_preamble -> txm_module_preamble_start_stop_stack_size;
+ callback_stack_size = module_preamble -> txm_module_preamble_callback_stack_size;
+
+ TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_size, TXM_MODULE_DATA_ALIGNMENT, data_size);
+ data_size = ((data_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
+
+ /* Adjust the size of the module elements to be aligned to the default alignment. We do this
+ so that when we partition the allocated memory, we can simply place these regions right beside
+ each other without having to align their pointers. Note this only works when they all have
+ the same alignment. */
+
+ TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(start_stop_stack_size, TXM_MODULE_DATA_ALIGNMENT, start_stop_stack_size);
+ start_stop_stack_size = ((start_stop_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
+
+ TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(callback_stack_size, TXM_MODULE_DATA_ALIGNMENT, callback_stack_size);
+ callback_stack_size = ((callback_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
+
+ /* Update the data size to account for the default thread stacks. */
+ data_allocation_size = 0;
+ TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, start_stop_stack_size, data_allocation_size);
+ TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, callback_stack_size, data_allocation_size);
+
+ /* Setup the default code and data alignments. */
+ data_alignment = (ULONG) TXM_MODULE_DATA_ALIGNMENT;
+
+ /* Get the port-specific alignment for the data size. Note we only want data
+ so we pass values of 1 for code (to avoid any possible div by 0 errors). */
+ code_size_ignored = 1;
+ code_alignment_ignored = 1;
+ TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size_ignored, code_alignment_ignored, data_allocation_size, data_alignment)
+
+ /* Since this is an absolute load, check the alignment of the module's data area when the caller
+ supplied its location. */
+ if (module_data_location != TX_NULL)
+ {
+ if ((((ALIGN_TYPE) module_data_location) & (((ALIGN_TYPE) data_alignment) - ((ALIGN_TYPE) 1))) != ((ALIGN_TYPE) 0))
+ {
+
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Invalid alignment, return error. */
+ return(TXM_MODULE_ALIGNMENT_ERROR);
+ }
+ }
+
+ /* Calculate the module's total RAM memory requirement. This entire area is allocated from the module
+ manager's byte pool. The general layout is defined as follows:
+
+ Lowest Address: Start of start/stop thread stack
+ ... [note: thread entry info is embedded near end of stack areas]
+ End of start/stop thread stack
+
+ Start of callback thread stack
+ ... [note: thread entry info is embedded near end of stack areas]
+ End of callback thread stack
+
+ Highest Address: */
+
+ /* Add an extra alignment increment so we can align the pointer after allocation. */
+ TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, data_alignment, data_allocation_size);
+
+ /* Allocate memory for the module. */
+ status = _tx_byte_allocate(&_txm_module_manager_byte_pool, (VOID **) &memory_ptr, data_allocation_size, TX_NO_WAIT);
+
+ /* Determine if the module memory allocation was successful. */
+ if (status)
+ {
+
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* No memory, return an error. */
+ return(TX_NO_MEMORY);
+ }
+
+ /* Clear the allocated memory. */
+ TX_MEMSET(memory_ptr, ((UCHAR) 0), data_allocation_size);
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Setup the module instance structure. */
+ module_instance -> txm_module_instance_id = TXM_MODULE_ID;
+
+ /* Save the module name. */
+ module_instance -> txm_module_instance_name = module_name;
+
+ /* Save the module properties. */
+ module_instance -> txm_module_instance_property_flags = module_preamble -> txm_module_preamble_property_flags;
+
+ /* Set the module data memory allocation. This is the address released
+ when the module is unloaded. */
+ module_instance -> txm_module_instance_data_allocation_ptr = (VOID *) memory_ptr;
+
+ /* Save the data allocation size. */
+ module_instance -> txm_module_instance_data_allocation_size = data_allocation_size;
+
+ /* Calculate the actual start of the data area. This needs to be adjusted based on the alignment. */
+ data_start = (ALIGN_TYPE) memory_ptr;
+ data_start = (data_start + (((ALIGN_TYPE)data_alignment) - 1)) & ~(((ALIGN_TYPE)data_alignment) - 1);
+ memory_ptr = (CHAR *) data_start;
+
+ /* Compute the beginning and end of the data area. An absolutely located module has its data
+ placed at a fixed address by its linker script, and that address is not carried in the
+ module preamble. It must therefore be supplied by the caller. */
+ if (module_data_location != TX_NULL)
+ {
+
+ module_instance -> txm_module_instance_data_start = module_data_location;
+
+ /* A zero data size is valid, so guard against wrapping when computing the end address. */
+ if (data_size != 0)
+ {
+ module_instance -> txm_module_instance_data_end = (VOID *) (((CHAR *) module_data_location) + (data_size - 1));
+ }
+ else
+ {
+ module_instance -> txm_module_instance_data_end = module_data_location;
+ }
+
+ /* Save the size of the data area. */
+ module_instance -> txm_module_instance_data_size = data_size;
+ }
+ else
+ {
+
+ /* The caller does not know where the module's data area is, so the module instance cannot
+ describe it. Report an empty data area rather than an invalid one. */
+ module_instance -> txm_module_instance_data_start = TX_NULL;
+ module_instance -> txm_module_instance_data_end = TX_NULL;
+
+ /* Save the size of the data area. */
+ module_instance -> txm_module_instance_data_size = 0;
+ }
+
+ /* Set the module code memory allocation. This is the address released
+ when the module is unloaded. */
+ module_instance -> txm_module_instance_code_allocation_ptr = (VOID *) NULL;
+
+ /* Save the code allocation size. */
+ module_instance -> txm_module_instance_code_allocation_size = 0;
+
+ /* Setup the code pointers. Since the code was loaded in-place, this is effectively just the values supplied in the API call. */
+ module_instance -> txm_module_instance_code_start = (VOID *) module_location;
+ module_instance -> txm_module_instance_code_end = (VOID *) (((CHAR *) module_location) + (code_size - 1));
+
+ /* Setup the code size. */
+ module_instance -> txm_module_instance_code_size = code_size;
+
+ /* Save the module's total memory usage. */
+ module_instance -> txm_module_instance_total_ram_usage = 0 /* Code is executed in place */ + data_allocation_size /* just the size of stacks */;
+
+ /* Set the module state to started. */
+ module_instance -> txm_module_instance_state = TXM_MODULE_LOADED;
+
+ /* Save the preamble pointer. */
+ module_instance -> txm_module_instance_preamble_ptr = module_preamble;
+
+ /* Save the module application ID in the module instance. */
+ module_instance -> txm_module_instance_application_module_id = module_preamble -> txm_module_preamble_application_module_id;
+
+ /* Setup the module's start/stop thread stack area. */
+ module_instance -> txm_module_instance_start_stop_stack_start_address = (VOID *) (memory_ptr);
+ module_instance -> txm_module_instance_start_stop_stack_size = start_stop_stack_size;
+ module_instance -> txm_module_instance_start_stop_stack_end_address = (VOID *) (memory_ptr + (start_stop_stack_size - 1));
+
+ /* Move the memory pointer forward. */
+ memory_ptr = memory_ptr + start_stop_stack_size;
+
+ /* Save the start/stop thread priority. */
+ module_instance -> txm_module_instance_start_stop_priority = module_preamble -> txm_module_preamble_start_stop_priority;
+
+ /* Setup the module's callback thread stack area. */
+ module_instance -> txm_module_instance_callback_stack_start_address = (VOID *) (memory_ptr);
+ module_instance -> txm_module_instance_callback_stack_size = callback_stack_size;
+ module_instance -> txm_module_instance_callback_stack_end_address = (VOID *) (memory_ptr + (callback_stack_size - 1));
+
+ /* Save the callback thread priority. */
+ module_instance -> txm_module_instance_callback_priority = module_preamble -> txm_module_preamble_callback_priority;
+
+ /* Setup the start of the module data section. For an absolute load, the byte pool allocation
+ holds only the two default thread stacks. The module's data section is the absolutely
+ located area supplied by the caller. */
+ module_instance -> txm_module_instance_module_data_base_address = module_data_location;
+
+ /* Build actual addresses based on load... Setup all the function pointers. Any adjustments needed to shell entry, start function, and callback function are defined in the
+ module preamble. */
+#ifdef ALIGN_TYPE_DEFINED
+ module_instance -> txm_module_instance_shell_entry_function = (VOID (*)(TX_THREAD *, TXM_MODULE_INSTANCE *)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_shell_entry_function);
+ module_instance -> txm_module_instance_start_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_start_function);
+ module_instance -> txm_module_instance_callback_request_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_callback_function);
+#else
+ module_instance -> txm_module_instance_shell_entry_function = (VOID (*)(TX_THREAD *, TXM_MODULE_INSTANCE *)) ((VOID *) module_preamble -> txm_module_preamble_shell_entry_function);
+ module_instance -> txm_module_instance_start_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_start_function);
+ module_instance -> txm_module_instance_callback_request_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_callback_function);
+#endif
+
+ /* Determine if there is a stop function for this module. */
+ if (module_preamble -> txm_module_preamble_stop_function)
+ {
+
+ /* Yes, there is a stop function, build the address. */
+#ifdef ALIGN_TYPE_DEFINED
+ module_instance -> txm_module_instance_stop_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_stop_function);
+#else
+ module_instance -> txm_module_instance_stop_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_stop_function);
+#endif
+ }
+ else
+ {
+
+ /* No, there is no stop function. Just set the pointer to NULL. */
+ module_instance -> txm_module_instance_stop_thread_entry = TX_NULL;
+ }
+
+ /* Load the module control block with port-specific information. */
+ TXM_MODULE_MANAGER_MODULE_SETUP(module_instance);
+
+ /* Now add the module to the linked list of created modules. */
+ if (_txm_module_manger_loaded_count++ == 0)
+ {
+
+ /* The loaded module list is empty. Add module to empty list. */
+ _txm_module_manager_loaded_list_ptr = module_instance;
+ module_instance -> txm_module_instance_loaded_next = module_instance;
+ module_instance -> txm_module_instance_loaded_previous = module_instance;
+ }
+ else
+ {
+
+ /* This list is not NULL, add to the end of the list. */
+ next_module = _txm_module_manager_loaded_list_ptr;
+ previous_module = next_module -> txm_module_instance_loaded_previous;
+
+ /* Place the new module in the list. */
+ next_module -> txm_module_instance_loaded_previous = module_instance;
+ previous_module -> txm_module_instance_loaded_next = module_instance;
+
+ /* Setup this module's created links. */
+ module_instance -> txm_module_instance_loaded_previous = previous_module;
+ module_instance -> txm_module_instance_loaded_next = next_module;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Return success. */
+ return(TX_SUCCESS);
+}
diff --git a/common_modules/module_manager/src/txm_module_manager_object_allocate.c b/common_modules/module_manager/src/txm_module_manager_object_allocate.c
index 92ae128c..8e452b44 100644
--- a/common_modules/module_manager/src/txm_module_manager_object_allocate.c
+++ b/common_modules/module_manager/src/txm_module_manager_object_allocate.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -23,6 +25,7 @@
#define TX_SOURCE_CODE
#include "txm_module.h"
+#include "txm_module_manager_util.h"
/**************************************************************************/
/* */
@@ -51,6 +54,11 @@
/* OUTPUT */
/* */
/* status Completion status */
+/* TXM_MODULE_MATH_OVERFLOW is */
+/* returned when object_size is so */
+/* large that adding the manager's */
+/* own object header to it would */
+/* not be representable */
/* */
/* CALLS */
/* */
@@ -67,6 +75,7 @@ UINT _txm_module_manager_object_allocate(VOID **object_ptr_ptr, ULONG object_siz
{
TXM_MODULE_ALLOCATED_OBJECT *object_ptr;
+ULONG allocation_size;
UINT return_value;
@@ -81,6 +90,18 @@ UINT return_value;
/* Initialize the return pointer to NULL. */
*((VOID **) object_ptr_ptr) = TX_NULL;
+ /* Work out how much memory the pool must supply: the size the caller asked for plus
+ the private header this function writes in front of it. The size is supplied by
+ the module, so the addition is checked. An unchecked one wraps for sizes near the
+ top of a ULONG and asks the pool for fewer bytes than the header alone occupies,
+ after which the header stores below run past the end of the allocation and into
+ the neighbouring pool block. Sizes that survive the addition but exceed the pool
+ are refused by _txe_byte_allocate, which bounds every request by the pool size.
+
+ This is done before the protection mutex is taken so that a refused request leaves
+ the object pool, the module's allocated object list and its count untouched. */
+ TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(object_size, (ULONG) sizeof(TXM_MODULE_ALLOCATED_OBJECT), allocation_size);
+
/* Get module manager protection mutex. */
_txe_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
@@ -90,10 +111,10 @@ UINT return_value;
TXM_MODULE_ALLOCATED_OBJECT *next_object, *previous_object;
- /* Allocate the object requested by the module - adding an extra ULONG in order to
- store the module instance pointer. */
+ /* Allocate the object requested by the module, including the header checked above
+ that holds the owning module instance, the allocation list links and the size. */
return_value = (ULONG) _txe_byte_allocate(&_txm_module_manager_object_pool, (VOID **) &object_ptr,
- (ULONG) (object_size + sizeof(TXM_MODULE_ALLOCATED_OBJECT)), TX_NO_WAIT);
+ allocation_size, TX_NO_WAIT);
/* Determine if the request was successful. */
if (return_value == TX_SUCCESS)
diff --git a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c
index 2efc465b..c9a9ed4f 100644
--- a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c
+++ b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -25,6 +27,7 @@
#include "tx_api.h"
#include "tx_thread.h"
#include "txm_module.h"
+#include "txm_module_manager_util.h"
/**************************************************************************/
/* */
@@ -38,7 +41,29 @@
/* */
/* DESCRIPTION */
/* */
-/* This function deallocates a previously allocated object. */
+/* DEPRECATED. This function is called internally by the Module */
+/* Manager dispatch layer after a successful tx_*_delete() call from */
+/* a module. It must not be called directly by module or application */
+/* code. */
+/* */
+/* Module authors: remove any explicit call to */
+/* txm_module_object_deallocate(). Calling the appropriate */
+/* tx_*_delete() service is sufficient; pool deallocation is handled */
+/* automatically by the dispatch layer. */
+/* */
+/* Only memory the calling module allocated from the object pool is */
+/* released, and the allocation is identified by searching the */
+/* module's own allocation list rather than by reading a private */
+/* header from in front of the address the caller supplied. An */
+/* address that names none of this module's allocations returns */
+/* TX_PTR_ERROR and is not dereferenced. */
+/* Memory holding a live kernel object is not given back. Such a */
+/* request returns TX_DELETE_ERROR and changes nothing: the object */
+/* stays created, the allocation stays on the module's allocation */
+/* list, and the memory stays owned by the module. Storage that was */
+/* allocated but never made into an object is still released, so a */
+/* module can still clean up after a create that failed or was */
+/* abandoned. */
/* */
/* INPUT */
/* */
@@ -52,6 +77,9 @@
/* */
/* _txe_mutex_get Get module instance mutex */
/* _txe_mutex_put Release module instance mutex */
+/* _txm_module_manager_allocated_object_find */
+/* Find the module's allocation */
+/* _txm_module_manager_live_object_check Check for a live object */
/* _txe_byte_release Release object back to pool */
/* */
/* */
@@ -78,18 +106,65 @@ UINT return_value;
/* Pickup module instance pointer. */
module_instance = _tx_thread_current_ptr -> tx_thread_module_instance_ptr;
- /* Setup the memory pointer. */
- module_allocated_object_ptr = (TXM_MODULE_ALLOCATED_OBJECT *) object_ptr;
+ /* Find the allocation this address names.
+
+ The private header in front of an allocation is the manager's own
+ record of who the memory belongs to, but it is only a header when the
+ address is one the manager gave out. Reaching it by subtraction from
+ whatever address the caller supplied assumes the answer: for an object
+ the application allocated statically, or for any address outside the
+ object pool, the words in front of it are unrelated memory, and this
+ read them in privileged mode before deciding they were not a header.
+ Every delete dispatcher reaches this function with the address the
+ module named, so an object the module does not own arrived here as a
+ matter of course rather than exceptionally.
- /* Position the object pointer backwards to position back to the module manager information. */
- previous_object = module_allocated_object_ptr--;
+ Searching the module's own allocation list answers the same question
+ without that assumption. The address is compared against the
+ allocations the manager made for this module and is never
+ dereferenced, so an address that names none of them -- an object the
+ application owns, an object another module owns, or an address nowhere
+ near the object pool -- is refused without a privileged read. The
+ search also establishes what the header read could not: that the
+ address is the exact start of an allocation rather than somewhere
+ inside one. */
+ module_allocated_object_ptr = _txm_module_manager_allocated_object_find(module_instance, (ALIGN_TYPE) object_ptr, TX_NULL);
/* Make sure the object is valid. */
- if ((module_allocated_object_ptr == TX_NULL) || (module_allocated_object_ptr -> txm_module_allocated_object_module_instance != module_instance) || (module_instance -> txm_module_instance_object_list_count == 0))
+ if (module_allocated_object_ptr == TX_NULL)
{
/* Set return value to invalid pointer. */
return_value = TX_PTR_ERROR;
}
+
+ /* Determine if a live kernel object is in this memory.
+
+ Releasing the memory of a created object leaves the kernel holding the
+ only references to it. The object stays on the created list for its
+ type, a thread stays on the ready or suspension list it was on and stays
+ schedulable, and an active timer stays on the timer list. None of those
+ consult a control block ID, so nothing about the freed memory stops the
+ kernel using it: a created list walk reads a name pointer out of it, a
+ create or delete of another object of the same type writes through the
+ links in it, the scheduler restores a context from the stack pointer in
+ it, and timer expiration calls the function pointer in it. The byte pool
+ is meanwhile free to hand those bytes to the next allocation, so what the
+ kernel goes on reading as a control block is whatever the next owner of
+ the memory puts there.
+
+ This is asked before the allocation is unlinked, so a refusal leaves the
+ allocation list, the object and the memory exactly as they were. What is
+ refused is releasing the memory of an object that is still created; an
+ allocation that was never made into an object, or one whose object has
+ been deleted, is released as before, which is what keeps cleanup after a
+ failed or abandoned create working and what makes the release the delete
+ dispatchers perform after a successful delete go through. */
+ else if (_txm_module_manager_live_object_check((ALIGN_TYPE) object_ptr) == TX_TRUE)
+ {
+
+ /* Set return value to indicate the object must be deleted first. */
+ return_value = TX_DELETE_ERROR;
+ }
else
{
@@ -115,6 +190,27 @@ UINT return_value;
}
}
+ /* Clear the first word of the object being given back, which for every kernel
+ object is its control block ID.
+
+ Object authentication reads that ID to establish the type of an object and
+ that it is still created, having first established that the address is the
+ exact start of an allocation. The kernel clears the ID when it deletes an
+ object, so the ordinary sequence of delete and then deallocate has already
+ cleared it. What has not is a deallocation of an object that was never
+ deleted: the memory returns to the pool still carrying a valid ID, and the
+ next allocation to be placed there is a raw allocation that presents one.
+ Clearing it here means the manager stops vouching for a control block at
+ the moment it stops owning the memory, whatever order the module chose.
+
+ An allocation too small to hold an ID cannot be presenting one, and is
+ left alone rather than written past its end. */
+ if (module_allocated_object_ptr -> txm_module_object_size >= ((ULONG) sizeof(ULONG)))
+ {
+
+ *((ULONG *) object_ptr) = TX_CLEAR_ID;
+ }
+
/* Release the object memory. */
return_value = (ULONG) _txe_byte_release((VOID *) module_allocated_object_ptr);
}
diff --git a/common_modules/module_manager/src/txm_module_manager_object_pointer_get.c b/common_modules/module_manager/src/txm_module_manager_object_pointer_get.c
index 84cf6c96..8b24558b 100644
--- a/common_modules/module_manager/src/txm_module_manager_object_pointer_get.c
+++ b/common_modules/module_manager/src/txm_module_manager_object_pointer_get.c
@@ -37,9 +37,10 @@
/* */
/* DESCRIPTION */
/* */
-/* This function is deprecated and calls the secure version of this */
-/* function (_txm_module_manager_object_pointer_get_extended) with the */
-/* maximum possible name length since none was passed. */
+/* DEPRECATED. Use _txm_module_manager_object_pointer_get_extended() */
+/* instead, passing the actual name-buffer length. This wrapper */
+/* passes UINT_MAX as the length, which can cause the name-comparison */
+/* loop to read past the end of a short buffer (undefined behaviour). */
/* */
/* INPUT */
/* */
diff --git a/common_modules/module_manager/src/txm_module_manager_thread_create.c b/common_modules/module_manager/src/txm_module_manager_thread_create.c
index c14d8e4e..51b85e1b 100644
--- a/common_modules/module_manager/src/txm_module_manager_thread_create.c
+++ b/common_modules/module_manager/src/txm_module_manager_thread_create.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -82,7 +84,7 @@
/* _txm_module_manager_kernel_dispatch Kernel dispatch function */
/* */
/**************************************************************************/
-UINT _txm_module_manager_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr,
+UINT _txm_module_manager_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr,
VOID (*shell_function)(TX_THREAD *, TXM_MODULE_INSTANCE *),
VOID (*entry_function)(ULONG id), ULONG entry_input,
VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold,
@@ -104,6 +106,9 @@ UCHAR *temp_ptr;
ALIGN_TYPE new_stack_start;
ALIGN_TYPE updated_stack_start;
#endif
+#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) && !defined(TX_DISABLE_STACK_FILLING)
+ULONG stack_fill_value;
+#endif
TXM_MODULE_THREAD_ENTRY_INFO *thread_entry_info;
VOID *stack_end;
ULONG i;
@@ -261,13 +266,18 @@ ULONG i;
#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING)
/* Initialize the stack fill value to a 8-bit random value. */
- thread_ptr -> tx_thread_stack_fill_value = ((ULONG) TX_RAND()) & 0xFFUL;
+ stack_fill_value = ((ULONG) TX_RAND()) & 0xFFUL;
/* Duplicate the random value in each of the 4 bytes of the stack fill value. */
- thread_ptr -> tx_thread_stack_fill_value = thread_ptr -> tx_thread_stack_fill_value |
- (thread_ptr -> tx_thread_stack_fill_value << 8) |
- (thread_ptr -> tx_thread_stack_fill_value << 16) |
- (thread_ptr -> tx_thread_stack_fill_value << 24);
+ stack_fill_value = stack_fill_value |
+ (stack_fill_value << 8) |
+ (stack_fill_value << 16) |
+ (stack_fill_value << 24);
+
+ /* Store the fill value in the control block so that the stack fill below picks it up
+ through the TX_STACK_FILL macro. The control block is cleared further down in this
+ function, so the value is stored again once that has been done. */
+ thread_ptr -> tx_thread_stack_fill_value = stack_fill_value;
#endif
/* Set the thread stack to a pattern prior to creating the initial
@@ -284,7 +294,7 @@ ULONG i;
stack_size = ((stack_size/(sizeof(ULONG))) * (sizeof(ULONG))) - (sizeof(ULONG));
/* Ensure the starting stack address is evenly aligned. */
- new_stack_start = TX_POINTER_TO_ALIGN_TYPE_CONVERT(stack_start);
+ new_stack_start = (ALIGN_TYPE) ((VOID *) stack_start);
updated_stack_start = ((((ULONG) new_stack_start) + ((sizeof(ULONG)) - ((ULONG) 1)) ) & (~((sizeof(ULONG)) - ((ULONG) 1))));
/* Determine if the starting stack address is different. */
@@ -296,7 +306,7 @@ ULONG i;
}
/* Update the starting stack pointer. */
- stack_start = TX_ALIGN_TYPE_TO_POINTER_CONVERT(updated_stack_start);
+ stack_start = (VOID *) ((ALIGN_TYPE) updated_stack_start);
#endif
/* Allocate the thread entry information at the top of thread's stack - Leaving one
@@ -309,6 +319,21 @@ ULONG i;
/* Initialize thread control block to all zeros. */
TX_MEMSET(thread_ptr, 0, sizeof(TX_THREAD));
+#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) && !defined(TX_DISABLE_STACK_FILLING)
+
+ /* Clearing the control block reset the stack fill value, so store the value that was
+ actually used to fill the stack again. Otherwise the stack checking and stack analyze
+ routines would look for a pattern that is not the one present in the stack. */
+ thread_ptr -> tx_thread_stack_fill_value = stack_fill_value;
+#endif
+
+ /* Note that TX_ENABLE_STACK_CHECKING is not supported for module threads. A user mode
+ module thread owns two stacks and the scheduler swaps tx_thread_stack_start,
+ tx_thread_stack_end and tx_thread_stack_size over to the kernel stack whenever the
+ thread enters the module manager. Neither tx_thread_stack_highest_ptr nor the guard
+ pattern beyond the end of the stack is maintained across that switch, so
+ TX_THREAD_STACK_CHECK may report spurious stack errors for module threads. */
+
/* If the thread runs on user mode, allocate the kernel stack for syscall. */
if((module_instance -> txm_module_instance_property_flags) & TXM_MODULE_USER_MODE)
{
@@ -331,8 +356,10 @@ ULONG i;
/* Align kernel stack pointer. */
thread_ptr -> tx_thread_module_kernel_stack_end = (VOID *) (((ALIGN_TYPE)(thread_ptr -> tx_thread_module_kernel_stack_start) + TXM_MODULE_KERNEL_STACK_SIZE) & ~0x07);
- /* Set kernel stack size. */
- thread_ptr -> tx_thread_module_kernel_stack_size = TXM_MODULE_KERNEL_STACK_SIZE;
+ /* Set kernel stack size. Aligning the end of the kernel stack downwards can consume
+ up to seven bytes of the block returned by the allocator, so the usable size must be
+ derived from the aligned range instead of from TXM_MODULE_KERNEL_STACK_SIZE. */
+ thread_ptr -> tx_thread_module_kernel_stack_size = (ULONG) ((ALIGN_TYPE) (thread_ptr -> tx_thread_module_kernel_stack_end) - (ALIGN_TYPE) (thread_ptr -> tx_thread_module_kernel_stack_start));
}
#if TXM_MODULE_MEMORY_PROTECTION
@@ -741,4 +768,3 @@ ULONG i;
/* Return success. */
return(TX_SUCCESS);
}
-
diff --git a/common_modules/module_manager/src/txm_module_manager_thread_reset.c b/common_modules/module_manager/src/txm_module_manager_thread_reset.c
index 75dd4a49..334070bf 100644
--- a/common_modules/module_manager/src/txm_module_manager_thread_reset.c
+++ b/common_modules/module_manager/src/txm_module_manager_thread_reset.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -106,6 +108,20 @@ TXM_MODULE_THREAD_ENTRY_INFO *thread_entry_info;
status = TX_NOT_DONE;
}
}
+
+ /* Resetting a thread means rebuilding its stack around a module's shell entry
+ function, so the thread has to be one a module manager created. A thread the
+ application created carries no module instance, and the fields this function
+ goes on to read from it -- the shell entry function it builds the new stack
+ frame around -- would be read through a null pointer in privileged mode. A
+ module can name such a thread: any thread the system created can be found by
+ name, and one that has run to completion satisfies the state test above. */
+ if (thread_ptr -> tx_thread_module_instance_ptr == TX_NULL)
+ {
+
+ /* Not a module thread, so there is nothing here to reset. */
+ status = TX_NOT_DONE;
+ }
}
/* Is the request valid? */
diff --git a/common_modules/module_manager/src/txm_module_manager_util.c b/common_modules/module_manager/src/txm_module_manager_util.c
index 78031b5f..f3c8beef 100644
--- a/common_modules/module_manager/src/txm_module_manager_util.c
+++ b/common_modules/module_manager/src/txm_module_manager_util.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -25,6 +27,15 @@
#define TX_SOURCE_CODE
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_queue.h"
+#include "tx_event_flags.h"
+#include "tx_semaphore.h"
+#include "tx_mutex.h"
+#include "tx_block_pool.h"
+#include "tx_byte_pool.h"
#include "txm_module.h"
#include "txm_module_manager_util.h"
@@ -270,7 +281,7 @@ UINT return_value;
/* 09-30-2020 Scott Larson Initial Version 6.1 */
/* */
/**************************************************************************/
-UINT _txm_module_manager_object_name_compare(CHAR *search_name, UINT search_name_length, CHAR *object_name)
+UINT _txm_module_manager_object_name_compare(CHAR *search_name, UINT search_name_length, TX_NAME_CONST CHAR *object_name)
{
CHAR search_name_char;
@@ -461,11 +472,525 @@ UINT _txm_module_manager_param_check_object_for_use(TXM_MODULE_INSTANCE *modu
return(TX_FALSE);
}
- /* Determine if the object pointer is inside the module object pool. */
+ /* Determine if the object is outside the calling module. */
if (TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, object_ptr, object_size) == TX_FALSE)
{
- /* Object pointer is not inside the object pool, which is invalid. */
+ /* Object pointer is not outside the module, which is invalid. */
+ return(TX_FALSE);
+ }
+
+ /* Being outside the module does not make an address an object. The manager's
+ object pool is outside every module, so an address shifted into the interior of
+ one of this module's own privileged allocations satisfies the test above while
+ denoting no object at all, and the bytes the shifted address then presents as a
+ control block are bytes the module chose through ordinary create and set
+ services. An address in the object pool is therefore only usable if it is the
+ exact address the manager handed out for an allocation of this size.
+
+ This function is given a size rather than a type, so it can go no further than
+ that: it cannot establish which type of object it is, and it cannot authenticate
+ an application-owned object outside the pool. Dispatchers in this repository use
+ _txm_module_manager_param_check_typed_object_for_use, which does both. */
+ if ((_txm_module_manager_object_pool_created == TX_TRUE) &&
+ (object_ptr >= (ALIGN_TYPE) _txm_module_manager_object_pool.tx_byte_pool_start) &&
+ (object_ptr < (ALIGN_TYPE) (_txm_module_manager_object_pool.tx_byte_pool_start + _txm_module_manager_object_pool.tx_byte_pool_size)))
+ {
+
+ if (_txm_module_manager_allocated_object_check(module_instance, object_ptr, object_size) == TX_FALSE)
+ {
+
+ /* An address in the object pool that is not the exact start of one of this
+ module's allocations, which is invalid. */
+ return(TX_FALSE);
+ }
+ }
+
+ /* Define application-specific object memory check. */
+#ifdef TXM_MODULE_MANGER_APPLICATION_VALID_OBJECT_MEMORY_CHECK
+
+ /* Bring in the application-spefic objeft memory check, defined by the user. */
+ TXM_MODULE_MANGER_APPLICATION_VALID_OBJECT_MEMORY_CHECK
+#endif /* TXM_MODULE_MANGER_APPLICATION_VALID_OBJECT_MEMORY_ENABLE */
+
+ /* Everything is okay with the object, return TX_TRUE. */
+ return(TX_TRUE);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_object_type_size_get PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function returns the size of the control block belonging to a */
+/* module object type. It is the size a service of that type is */
+/* entitled to dereference, and the size the manager recorded when it */
+/* allocated object memory for that type. */
+/* */
+/* INPUT */
+/* */
+/* object_type Module object type */
+/* object_size Destination for the control block */
+/* size of that type */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE Known object type */
+/* TX_FALSE Unknown object type */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_param_check_typed_object_for_use */
+/* Module object authentication */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_object_type_size_get(UINT object_type, ULONG *object_size)
+{
+
+UINT status;
+
+
+ /* Assume the type is one this manager knows. */
+ status = TX_TRUE;
+
+ switch (object_type)
+ {
+
+ case TXM_BLOCK_POOL_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_BLOCK_POOL);
+ break;
+
+ case TXM_BYTE_POOL_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_BYTE_POOL);
+ break;
+
+ case TXM_EVENT_FLAGS_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_EVENT_FLAGS_GROUP);
+ break;
+
+ case TXM_MUTEX_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_MUTEX);
+ break;
+
+ case TXM_QUEUE_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_QUEUE);
+ break;
+
+ case TXM_SEMAPHORE_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_SEMAPHORE);
+ break;
+
+ case TXM_THREAD_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_THREAD);
+ break;
+
+ case TXM_TIMER_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_TIMER);
+ break;
+
+ default:
+
+ /* Not a type the manager authenticates. Report it rather than guessing a
+ size, so that a caller cannot be given a range to validate that has no
+ relationship to the object the service will dereference. */
+ *object_size = ((ULONG) 0);
+ status = TX_FALSE;
+ break;
+ }
+
+ return(status);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_allocated_object_find PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function returns the manager's private header for the object */
+/* allocation an address names, or TX_NULL when the address names */
+/* none of the specified module's allocations. The size the */
+/* allocation was made for is reported to callers that ask for it. */
+/* */
+/* The allocation list is the manager's own record, built as it hands */
+/* object memory out, and it is searched rather than reached through */
+/* a header taken from in front of the caller's address. That order */
+/* is what makes the answer both correct and safe. */
+/* */
+/* Correct, because the address immediately after a header is the */
+/* only address in an allocation that the manager ever gave out, so */
+/* an address chosen inside an allocation is distinguishable from the */
+/* start of one. Reading a header cannot make that distinction: the */
+/* bytes in front of an interior address are part of the object, and */
+/* a module places values there through ordinary services. */
+/* */
+/* Safe, because the caller's address is only ever compared, never */
+/* dereferenced. An address that belongs to no allocation of this */
+/* module -- an object the application owns, an object another module */
+/* owns, or an address nowhere near the object pool -- is rejected */
+/* without a privileged read of the words in front of it. */
+/* */
+/* INPUT */
+/* */
+/* module_instance Requesting module instance pointer*/
+/* object_ptr Address of object memory area */
+/* object_size_ptr Address to return the size the */
+/* allocation was made for, or */
+/* TX_NULL to not return it */
+/* */
+/* OUTPUT */
+/* */
+/* allocation The allocation's private header, */
+/* or TX_NULL when the address */
+/* names none of this module's */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_allocated_object_check */
+/* Module object ownership check */
+/* _txm_module_manager_object_deallocate Module object deallocation */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+TXM_MODULE_ALLOCATED_OBJECT *_txm_module_manager_allocated_object_find(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG *object_size_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TXM_MODULE_ALLOCATED_OBJECT *allocated_object_ptr;
+TXM_MODULE_ALLOCATED_OBJECT *found_object_ptr;
+ULONG objects_examined;
+
+
+ /* Assume the address names none of this module's allocations. */
+ found_object_ptr = TX_NULL;
+
+ /* Determine if there is a module whose allocations can be searched. A request
+ that does not come from a module owns no allocation. */
+ if (module_instance == TX_NULL)
+ {
+
+ /* Nothing to search, and nothing to report. */
+ return(TX_NULL);
+ }
+
+ /* Disable interrupts. The allocation list is maintained by threads holding the
+ manager protection mutex, so a scan that runs to completion with interrupts
+ disabled cannot observe it being changed, and unlike taking the mutex it adds
+ no blocking point and no priority inversion to a kernel request. */
+ TX_DISABLE
+
+ allocated_object_ptr = module_instance -> txm_module_instance_object_list_head;
+ objects_examined = ((ULONG) 0);
+
+ /* Loop through the objects allocated to this module. The loop is bounded by the
+ count the manager maintains alongside the list, so the cost of one search is
+ bounded by the number of objects this module has allocated, and a list whose
+ links have been damaged cannot make the scan run on. */
+ while ((objects_examined < module_instance -> txm_module_instance_object_list_count) &&
+ (allocated_object_ptr != TX_NULL))
+ {
+
+ /* The address the module was given is the one immediately after the private
+ header, so that is the only address in this allocation that names it. */
+ if (((ALIGN_TYPE) (allocated_object_ptr + 1)) == object_ptr)
+ {
+
+ /* Found it. An address matches at most one allocation, so there is
+ nothing further to look at. */
+ found_object_ptr = allocated_object_ptr;
+
+ /* Report the size this allocation was made for, if the caller asked for
+ it. It is read here, inside the scan, so that the answer cannot be
+ taken from a header that stopped being one after the search. */
+ if (object_size_ptr != TX_NULL)
+ {
+
+ *object_size_ptr = allocated_object_ptr -> txm_module_object_size;
+ }
+
+ break;
+ }
+
+ /* Move to the next allocated object. */
+ objects_examined++;
+ allocated_object_ptr = allocated_object_ptr -> txm_module_allocated_object_next;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ return(found_object_ptr);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_allocated_object_check PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function determines whether an address is the exact address */
+/* the manager handed the specified module for one of its object */
+/* allocations, and whether that allocation is the size the caller */
+/* expects. */
+/* */
+/* This is the question of ownership, and it is deliberately a */
+/* separate question from whether an object is there at all. A */
+/* module may hold, and legitimately use, a pointer to an object it */
+/* does not own: the manager hands application-owned objects to */
+/* modules by name through its object lookup service, and sharing an */
+/* object is what that service is for. Destroying one is not sharing */
+/* it, so the delete services ask this question in addition to the */
+/* ones that establish that the address denotes a usable object. */
+/* */
+/* INPUT */
+/* */
+/* module_instance Requesting module instance pointer*/
+/* object_ptr Address of object memory area */
+/* object_size Expected size of the allocation */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE An exact allocation of that size */
+/* TX_FALSE Anything else */
+/* */
+/* CALLS */
+/* */
+/* _txm_module_manager_allocated_object_find */
+/* Find the module's allocation */
+/* */
+/* CALLED BY */
+/* */
+/* txm_module_manager_* Module manager functions */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_allocated_object_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size)
+{
+
+ULONG allocated_size;
+UINT status;
+
+
+ /* Assume the address is not one of this module's allocations. */
+ status = TX_FALSE;
+
+ /* Initialize the size, so that nothing is read if no allocation is found. */
+ allocated_size = ((ULONG) 0);
+
+ /* Determine if the address is the exact start of one of this module's
+ allocations. */
+ if (_txm_module_manager_allocated_object_find(module_instance, object_ptr, &allocated_size) != TX_NULL)
+ {
+
+ /* Is the allocation the size the caller expects? An allocation made for a
+ smaller object does not become a larger one because a service was asked
+ to treat it as one. */
+ if (allocated_size == object_size)
+ {
+
+ status = TX_TRUE;
+ }
+ }
+
+ return(status);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_param_check_typed_object_for_use */
+/* PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function authenticates a kernel object a module has named, */
+/* before a privileged service is allowed to dereference it. It */
+/* establishes that the address is the exact address of a live kernel */
+/* object of the type the service expects. */
+/* */
+/* The address is accepted only if it is on the kernel's created list */
+/* for that type. That list is the record the create and delete */
+/* services maintain, so being on it establishes at once that the */
+/* address is an object start rather than an address inside an object, */
+/* that the object is of this type, and that it has not been deleted. */
+/* It is also how an object the application created and shared with a */
+/* module is authenticated, since the manager allocated no such object */
+/* and has no record of its own to consult. */
+/* */
+/* Nothing a module can influence is used to establish a type. In */
+/* particular the control block ID is not, on its own, evidence of */
+/* anything: a module can arrange for the value of an ID to appear */
+/* inside an object it legitimately owns, which is what lets a shifted */
+/* pointer pass an ID test, and distinct object types of equal size */
+/* exist, so an ID is not even a type at an address known to be an */
+/* object start. It is checked, after the created list has settled the */
+/* question, because it is the check the _txe_ services make and it is */
+/* compiled away with them under TX_DISABLE_ERROR_CHECKING. */
+/* */
+/* INPUT */
+/* */
+/* module_instance Requesting module instance pointer*/
+/* object_ptr Address of object memory area */
+/* object_type Module object type the service */
+/* expects */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE Authenticated object pointer */
+/* TX_FALSE Invalid object pointer */
+/* */
+/* CALLS */
+/* */
+/* _txm_module_manager_object_type_size_get */
+/* Get control block size */
+/* _txm_module_manager_created_object_type_check */
+/* Check kernel created list */
+/* _txm_module_manager_object_id_check Check control block ID */
+/* */
+/* CALLED BY */
+/* */
+/* txm_module_manager_* Module manager functions */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_param_check_typed_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, UINT object_type)
+{
+
+ULONG object_size;
+UINT exact_object;
+
+
+ /* Determine if the object pointer is NULL. */
+ if ((void *) object_ptr == TX_NULL)
+ {
+
+ /* Object pointer is NULL, which is invalid. */
+ return(TX_FALSE);
+ }
+
+ /* Pickup the size of the control block this type of service dereferences. */
+ if (_txm_module_manager_object_type_size_get(object_type, &object_size) == TX_FALSE)
+ {
+
+ /* Not an object type this manager authenticates, so it cannot be used. */
+ return(TX_FALSE);
+ }
+
+ /* Determine if the object is outside the calling module. A kernel object inside
+ the module's own memory is one the module can write behind the kernel's back,
+ so it is rejected here as it always has been. This also rejects a size that
+ wraps when added to the address. */
+ if (TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, object_ptr, object_size) == TX_FALSE)
+ {
+
+ /* Object pointer is not outside the module, which is invalid. */
+ return(TX_FALSE);
+ }
+
+ /* Establish that the address is the exact address of a live object of this type,
+ from the kernel's created list for the type. That list is the record the create
+ and delete services maintain, so being on it establishes at once that the
+ address is an object start, that the object is of this type, and that it has not
+ been deleted.
+
+ It is deliberately the only ground on which an address is accepted. The
+ manager's own allocation list would establish the address and the size of an
+ object a module allocated, and would do it by walking a shorter list, but it
+ records no type, and the type cannot then be taken from the control block
+ itself: distinct object types of equal size exist -- on a 32-bit target a byte
+ pool, a mutex and a timer are all the same size -- so a control block whose ID
+ has been made to read as one of them would be accepted as that type. Nothing a
+ module can influence is used to establish a type.
+
+ The address is not dereferenced to reach this decision. An address a module
+ named is not read until a kernel record says there is an object there. */
+ exact_object = _txm_module_manager_created_object_type_check(object_ptr, object_type);
+
+ if (exact_object == TX_FALSE)
+ {
+
+ /* The address is not the start of a live object of this type. */
+ return(TX_FALSE);
+ }
+
+ /* The address is a live object of the requested type. Confirm it against the
+ control block's own ID, which is the check the _txe_ services would make and
+ which is compiled away with them under TX_DISABLE_ERROR_CHECKING. */
+ if (_txm_module_manager_object_id_check(object_ptr, object_type) == TX_FALSE)
+ {
+
+ /* The created list and the control block disagree, so the object is not in a
+ state the manager is prepared to vouch for. */
return(TX_FALSE);
}
@@ -485,6 +1010,498 @@ UINT _txm_module_manager_param_check_object_for_use(TXM_MODULE_INSTANCE *modu
/* */
/* FUNCTION RELEASE */
/* */
+/* _txm_module_manager_created_object_type_check PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function determines whether an address is the exact address */
+/* of an object on the kernel's created list for a module object type. */
+/* */
+/* The created list is the record the create and delete services */
+/* maintain, so being on it establishes at once that the address is an */
+/* object start rather than an address inside an object, that the */
+/* object is of this type, and that it has not been deleted. It is */
+/* also the only record of an object the application created and */
+/* shared with a module, since the manager allocated no such object. */
+/* */
+/* Nothing the module can influence is consulted. In particular the */
+/* control block ID is not: a module can arrange for the value of an */
+/* ID to appear inside memory it owns, and distinct object types of */
+/* equal size exist, so an ID is not evidence that an object is there */
+/* nor of what type it is. */
+/* */
+/* INPUT */
+/* */
+/* object_ptr Address of object memory area */
+/* object_type Module object type */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE A created object of that type */
+/* TX_FALSE Anything else */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_live_object_check Module object liveness check */
+/* _txm_module_manager_param_check_typed_object_for_use */
+/* Module object authentication */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_created_object_type_check(ALIGN_TYPE object_ptr, UINT object_type)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+ULONG objects_examined;
+ULONG objects_created;
+ALIGN_TYPE candidate_ptr;
+UINT status;
+TX_BLOCK_POOL *block_pool_ptr;
+TX_BYTE_POOL *byte_pool_ptr;
+TX_EVENT_FLAGS_GROUP *event_flags_ptr;
+TX_MUTEX *mutex_ptr;
+TX_QUEUE *queue_ptr;
+TX_SEMAPHORE *semaphore_ptr;
+TX_THREAD *thread_ptr;
+TX_TIMER *timer_ptr;
+
+
+ /* Assume the address is not on the created list for this type. */
+ status = TX_FALSE;
+
+ /* Disable interrupts. The created lists are maintained with interrupts disabled,
+ so a scan that runs to completion this way sees a consistent list, and it adds
+ no blocking point to a kernel request. The cost of one check is bounded by the
+ number of objects of this type the system has created, which is the price of
+ authenticating an object the manager did not allocate; a module using its own
+ allocated objects does not reach this function. */
+ TX_DISABLE
+
+ /* Start each list from its head and pick up the count that bounds the walk, so a
+ list whose links have been damaged cannot make the scan run on. */
+ switch (object_type)
+ {
+
+ case TXM_BLOCK_POOL_OBJECT:
+
+ block_pool_ptr = _tx_block_pool_created_ptr;
+ objects_created = _tx_block_pool_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (block_pool_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) block_pool_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ block_pool_ptr = block_pool_ptr -> tx_block_pool_created_next;
+ }
+ break;
+
+ case TXM_BYTE_POOL_OBJECT:
+
+ byte_pool_ptr = _tx_byte_pool_created_ptr;
+ objects_created = _tx_byte_pool_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (byte_pool_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) byte_pool_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ byte_pool_ptr = byte_pool_ptr -> tx_byte_pool_created_next;
+ }
+ break;
+
+ case TXM_EVENT_FLAGS_OBJECT:
+
+ event_flags_ptr = _tx_event_flags_created_ptr;
+ objects_created = _tx_event_flags_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (event_flags_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) event_flags_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ event_flags_ptr = event_flags_ptr -> tx_event_flags_group_created_next;
+ }
+ break;
+
+ case TXM_MUTEX_OBJECT:
+
+ mutex_ptr = _tx_mutex_created_ptr;
+ objects_created = _tx_mutex_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (mutex_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) mutex_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ mutex_ptr = mutex_ptr -> tx_mutex_created_next;
+ }
+ break;
+
+ case TXM_QUEUE_OBJECT:
+
+ queue_ptr = _tx_queue_created_ptr;
+ objects_created = _tx_queue_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (queue_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) queue_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ queue_ptr = queue_ptr -> tx_queue_created_next;
+ }
+ break;
+
+ case TXM_SEMAPHORE_OBJECT:
+
+ semaphore_ptr = _tx_semaphore_created_ptr;
+ objects_created = _tx_semaphore_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (semaphore_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) semaphore_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ semaphore_ptr = semaphore_ptr -> tx_semaphore_created_next;
+ }
+ break;
+
+ case TXM_THREAD_OBJECT:
+
+ thread_ptr = _tx_thread_created_ptr;
+ objects_created = _tx_thread_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (thread_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) thread_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ thread_ptr = thread_ptr -> tx_thread_created_next;
+ }
+ break;
+
+ case TXM_TIMER_OBJECT:
+
+ timer_ptr = _tx_timer_created_ptr;
+ objects_created = _tx_timer_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (timer_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) timer_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ timer_ptr = timer_ptr -> tx_timer_created_next;
+ }
+ break;
+
+ default:
+
+ /* Not a type the manager authenticates. */
+ break;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ return(status);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_object_id_check PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function determines whether the control block at an object */
+/* start carries the ID of a module object type. The kernel writes */
+/* that ID when it creates an object and clears it when it deletes */
+/* one, so at an address already established to be an object start the */
+/* ID reports both the type and whether the object is still created. */
+/* */
+/* This check must not be used on its own to decide that an address is */
+/* an object. A module can place the value of an ID inside an object */
+/* it legitimately owns, so an ID found at an address the manager has */
+/* not otherwise authenticated proves nothing. */
+/* */
+/* The check matters most where the error checking layer is absent: */
+/* with TX_DISABLE_ERROR_CHECKING the _txe_ services that would */
+/* otherwise test the ID are compiled away, and this is then the only */
+/* ID test between a module and a privileged dereference. */
+/* */
+/* INPUT */
+/* */
+/* object_ptr Address of an object start */
+/* object_type Module object type */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE A created object of that type */
+/* TX_FALSE Anything else */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_param_check_typed_object_for_use */
+/* Module object authentication */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_object_id_check(ALIGN_TYPE object_ptr, UINT object_type)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+ULONG object_id;
+ULONG expected_id;
+UINT status;
+
+
+ /* Read the ID through a pointer to the type the caller named, so that the field
+ read is the one that type declares rather than an assumed offset. */
+ TX_DISABLE
+
+ switch (object_type)
+ {
+
+ case TXM_BLOCK_POOL_OBJECT:
+
+ object_id = ((TX_BLOCK_POOL *) object_ptr) -> tx_block_pool_id;
+ expected_id = TX_BLOCK_POOL_ID;
+ break;
+
+ case TXM_BYTE_POOL_OBJECT:
+
+ object_id = ((TX_BYTE_POOL *) object_ptr) -> tx_byte_pool_id;
+ expected_id = TX_BYTE_POOL_ID;
+ break;
+
+ case TXM_EVENT_FLAGS_OBJECT:
+
+ object_id = ((TX_EVENT_FLAGS_GROUP *) object_ptr) -> tx_event_flags_group_id;
+ expected_id = TX_EVENT_FLAGS_ID;
+ break;
+
+ case TXM_MUTEX_OBJECT:
+
+ object_id = ((TX_MUTEX *) object_ptr) -> tx_mutex_id;
+ expected_id = TX_MUTEX_ID;
+ break;
+
+ case TXM_QUEUE_OBJECT:
+
+ object_id = ((TX_QUEUE *) object_ptr) -> tx_queue_id;
+ expected_id = TX_QUEUE_ID;
+ break;
+
+ case TXM_SEMAPHORE_OBJECT:
+
+ object_id = ((TX_SEMAPHORE *) object_ptr) -> tx_semaphore_id;
+ expected_id = TX_SEMAPHORE_ID;
+ break;
+
+ case TXM_THREAD_OBJECT:
+
+ object_id = ((TX_THREAD *) object_ptr) -> tx_thread_id;
+ expected_id = TX_THREAD_ID;
+ break;
+
+ case TXM_TIMER_OBJECT:
+
+ object_id = ((TX_TIMER *) object_ptr) -> tx_timer_id;
+ expected_id = TX_TIMER_ID;
+ break;
+
+ default:
+
+ /* Not a type the manager authenticates. Choose values that cannot match. */
+ object_id = TX_CLEAR_ID;
+ expected_id = ~((ULONG) TX_CLEAR_ID);
+ break;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ if (object_id == expected_id)
+ {
+
+ status = TX_TRUE;
+ }
+ else
+ {
+
+ status = TX_FALSE;
+ }
+
+ return(status);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_live_object_check PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function determines whether an address is the exact address */
+/* of a live kernel object of any type the Module Manager knows. */
+/* */
+/* It answers the question object deallocation has to ask before it */
+/* gives memory back: is the kernel still going to use these bytes as */
+/* a control block. Deallocation is told an address and nothing else, */
+/* so unlike the checks a typed service makes it cannot be given the */
+/* type to look for, and every type has to be looked for in turn. */
+/* */
+/* The eight created lists are searched whatever the size of the */
+/* allocation at the address. Skipping a type whose control block is */
+/* larger than the allocation would be sound only if every object had */
+/* been created through a size-checked path, and a module running */
+/* without memory protection creates objects without one. */
+/* */
+/* Each list is searched in its own interrupts-disabled window rather */
+/* than all of them in one, so the longest window is bounded by the */
+/* number of objects of a single type. The whole search costs one pass */
+/* over the objects the system has created, and is paid once per */
+/* object deallocation. */
+/* */
+/* INPUT */
+/* */
+/* object_ptr Address of object memory area */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE A live kernel object is there */
+/* TX_FALSE Anything else */
+/* */
+/* CALLS */
+/* */
+/* _txm_module_manager_created_object_type_check */
+/* Check one kernel created list */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_object_deallocate Deallocate object memory */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_live_object_check(ALIGN_TYPE object_ptr)
+{
+
+UINT object_type;
+UINT status;
+
+
+ /* Assume no live object is there. */
+ status = TX_FALSE;
+
+ /* The eight module object types that have a kernel created list occupy a
+ contiguous range, so each is asked in turn by walking the range. A value in
+ the range that the per-type check does not recognise answers TX_FALSE, so a
+ type the manager stops knowing does not silently pass this search. */
+ for (object_type = ((UINT) TXM_BLOCK_POOL_OBJECT); object_type <= ((UINT) TXM_TIMER_OBJECT); object_type++)
+ {
+
+ if (_txm_module_manager_created_object_type_check(object_ptr, object_type) == TX_TRUE)
+ {
+
+ /* An address is the start of at most one object, so there is nothing
+ further to look for. */
+ status = TX_TRUE;
+ break;
+ }
+ }
+
+ return(status);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
/* _txm_module_manager_util_code_allocation_size_and_alignment_get */
/* PORTABLE C */
/* 6.1 */
diff --git a/common_modules/module_manager/utilities/module_binary_to_c_array.c b/common_modules/module_manager/utilities/module_binary_to_c_array.c
index da0cf97c..e418fbc1 100644
--- a/common_modules/module_manager/utilities/module_binary_to_c_array.c
+++ b/common_modules/module_manager/utilities/module_binary_to_c_array.c
@@ -1,3 +1,16 @@
+/***************************************************************************/
+/* Copyright (c) 2024 Microsoft Corporation */
+/* Copyright (c) 2026 Eclipse ThreadX contributors */
+/* */
+/* This program and the accompanying materials are made available under */
+/* the terms of the MIT License which is available at */
+/* https://opensource.org/licenses/MIT. */
+/* */
+/* SPDX-License-Identifier: MIT */
+/***************************************************************************/
+
+// Portions of this file were generated with AI assistance.
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -25,8 +38,11 @@ unsigned long column;
{
/* Print an error message out and wait for user key hit. */
- printf("module_binary_to_c_array.exe - Copyright (c) Microsoft Corporation v5.8\n");
- printf("**** Error: invalid input parameter for module_binary_to_c_array.exe **** \n");
+ printf("module_binary_to_c_array\n");
+ printf("(c) 2024 Microsoft Corp\n");
+ printf("(c) 2026 Eclipse ThreadX contributors\n");
+ printf("v6.5.2.202603\n");
+ printf("**** Error: invalid input parameter for module_binary_to_c_array **** \n");
printf(" Command Line Should be:\n\n");
printf(" > module_binary_to_c_array source_binary_file c_array_file <cr> \n\n");
return(1);
@@ -57,6 +73,10 @@ unsigned long column;
/* Print an error message out and wait for user key hit. */
printf("**** Error: invalid format of binary input file **** \n");
printf(" File: %s ", argv[1]);
+
+ /* Close the source file. */
+ fclose(source_file);
+
return(3);
}
@@ -75,7 +95,9 @@ unsigned long column;
fprintf(array_file, "/**************************** Module-Binary-to-C-array Utility **********************************/\n");
fprintf(array_file, "/* */\n");
- fprintf(array_file, "/* Copyright (c) Microsoft Corporation Version 5.4, build date: 03-01-2018 */\n");
+ fprintf(array_file, "/* Copyright (c) 2024 Microsoft Corp */\n");
+ fprintf(array_file, "/* Copyright (c) 2026 Eclipse ThreadX contributors */\n");
+ fprintf(array_file, "/* v6.5.2.202603 */\n");
fprintf(array_file, "/* */\n");
fprintf(array_file, "/************************************************************************************************/\n\n");
fprintf(array_file, "/* \n");
@@ -109,7 +131,7 @@ unsigned long column;
{
if (address != 0)
fprintf(array_file, ",\n");
- fprintf(array_file, "/* 0x%08X */ 0x%02X", address, (unsigned int) alpha);
+ fprintf(array_file, "/* 0x%08lX */ 0x%02X", address, (unsigned int) alpha);
}
else
fprintf(array_file, ", 0x%02X", (unsigned int) alpha);
diff --git a/common_modules/module_manager/utilities/module_to_binary.c b/common_modules/module_manager/utilities/module_to_binary.c
index bb4f294d..0b159cd7 100644
--- a/common_modules/module_manager/utilities/module_to_binary.c
+++ b/common_modules/module_manager/utilities/module_to_binary.c
@@ -9,11 +9,25 @@
/* SPDX-License-Identifier: MIT */
/***************************************************************************/
+// Portions of this file were generated with AI assistance.
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+/* MISRA C:2012 Rule 21.3 and Dir 4.12 deviation: dynamic memory is used in this
+ file. This is a host-side conversion utility executed on the development
+ machine, not ThreadX runtime code, and the ELF areas being read have sizes
+ that are only known at run time. Every allocation result is checked for NULL
+ and every buffer is released before its pointer is reused. */
+
+/* MISRA C:2012 Rule 15.5 (advisory) deviation: main() returns from several
+ error paths instead of having a single point of exit. The project forbids
+ goto, so an early return is the only way to abandon the conversion, and this
+ matches the style already used by the parameter and file open checks. */
+
+
/* Define the file handles. */
FILE *source_file;
@@ -137,13 +151,52 @@ unsigned char *buffer;
}
+/* Close the files and release the ELF areas allocated by main(). This is called
+ from every exit path taken after the files have been opened, so it must
+ tolerate being called with resources that were never acquired. The areas it
+ releases are the file scope pointers declared above. */
+
+static void converter_cleanup(void)
+{
+
+ /* Determine if the source file is open. */
+ if (source_file != NULL)
+ {
+
+ /* Close it. */
+ fclose(source_file);
+ source_file = NULL;
+ }
+
+ /* Determine if the binary output file is open. */
+ if (binary_file != NULL)
+ {
+
+ /* Close it. */
+ fclose(binary_file);
+ binary_file = NULL;
+ }
+
+ /* Release the ELF areas. Note that free() is defined to do nothing when it
+ is supplied a NULL pointer, so no test is required here. */
+ free(program_header);
+ program_header = NULL;
+ free(section_header);
+ section_header = NULL;
+ free(section_string_table);
+ section_string_table = NULL;
+ free(code_section_array);
+ code_section_array = NULL;
+}
+
+
int main(int argc, char* argv[])
{
unsigned long i, j;
-unsigned long current_total;
unsigned long address;
unsigned long size;
+unsigned long allocation_size;
unsigned char *code_buffer;
unsigned long code_section_index;
CODE_SECTION_ENTRY code_section_temp;
@@ -155,8 +208,11 @@ unsigned char zero_value;
{
/* Print an error message out and wait for user key hit. */
- printf("module_to_binary.exe - Copyright (c) Microsoft Corporation v5.8\n");
- printf("**** Error: invalid input parameter for module_to_binary.exe **** \n");
+ printf("module_to_binary\n");
+ printf("(c) 2024 Microsoft Corp\n");
+ printf("(c) 2026 Eclipse ThreadX contributors\n");
+ printf("v6.5.2.202603\n");
+ printf("**** Error: invalid input parameter for module_to_binary **** \n");
printf(" Command Line Should be:\n\n");
printf(" > module_to_binary source_elf_file c_binary_file <cr> \n\n");
return(1);
@@ -189,29 +245,140 @@ unsigned char zero_value;
}
/* Read the ELF header. */
- elf_object_read(0, &header, sizeof(header));
+ if (elf_object_read(0, &header, sizeof(header)) != 0)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: read failed on the ELF header **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(6);
+ }
/* Allocate memory for the program header(s). */
- program_header = malloc(sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries);
+ allocation_size = sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries;
+ program_header = malloc(allocation_size);
+
+ /* Determine if the memory allocation was successful. Note that an empty area
+ is not an error, since malloc() is permitted to return NULL for it. */
+ if ((program_header == NULL) && (allocation_size != 0))
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: memory allocation failed for the program header(s) **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(5);
+ }
/* Read the program header(s). */
- elf_object_read(header.elf_header_program_header_offset, program_header, (sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries));
+ if (elf_object_read(header.elf_header_program_header_offset, program_header, allocation_size) != 0)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: read failed on the program header(s) **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(6);
+ }
/* Allocate memory for the section header(s). */
- section_header = malloc(sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries);
+ allocation_size = sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries;
+ section_header = malloc(allocation_size);
+
+ /* Determine if the memory allocation was successful. */
+ if ((section_header == NULL) && (allocation_size != 0))
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: memory allocation failed for the section header(s) **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(5);
+ }
/* Read the section header(s). */
- elf_object_read(header.elf_header_section_header_offset, section_header, (sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries));
+ if (elf_object_read(header.elf_header_section_header_offset, section_header, allocation_size) != 0)
+ {
+ /* Print an error message out. */
+ printf("**** Error: read failed on the section header(s) **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(6);
+ }
+
+ /* Determine if the section string table index supplied by the ELF header is
+ inside the section header area that was just read. */
+ if (header.elf_header_section_string_index >= header.elf_header_section_header_entries)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: invalid section string table index in the ELF header **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(6);
+ }
/* Alocate memory for the section string table. */
- section_string_table = malloc(section_header[header.elf_header_section_string_index].elf_section_header_size);
+ allocation_size = section_header[header.elf_header_section_string_index].elf_section_header_size;
+ section_string_table = malloc(allocation_size);
+
+ /* Determine if the memory allocation was successful. */
+ if ((section_string_table == NULL) && (allocation_size != 0))
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: memory allocation failed for the section string table **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(5);
+ }
/* Read the section string table. */
- elf_object_read(section_header[header.elf_header_section_string_index].elf_section_header_offset, section_string_table, section_header[header.elf_header_section_string_index].elf_section_header_size);
+ if (elf_object_read(section_header[header.elf_header_section_string_index].elf_section_header_offset, section_string_table, allocation_size) != 0)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: read failed on the section string table **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(6);
+ }
/* Allocate memory for the code section array. */
- code_section_array = malloc(sizeof(CODE_SECTION_ENTRY)*header.elf_header_section_header_entries);
+ allocation_size = sizeof(CODE_SECTION_ENTRY)*header.elf_header_section_header_entries;
+ code_section_array = malloc(allocation_size);
+
+ /* Determine if the memory allocation was successful. */
+ if ((code_section_array == NULL) && (allocation_size != 0))
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: memory allocation failed for the code section array **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(5);
+ }
+
code_section_index = 0;
/* Print out the section header(s). */
@@ -258,9 +425,8 @@ unsigned char zero_value;
if (code_section_index == 0)
{
- /* Close files. */
- fclose(source_file);
- fclose(binary_file);
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
return(4);
}
@@ -310,9 +476,34 @@ unsigned char zero_value;
/* Now allocate memory for the code section. */
code_buffer = malloc(code_section_array[i].code_section_size);
+ /* Determine if the memory allocation was successful. */
+ if (code_buffer == NULL)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: memory allocation failed for code section **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(5);
+ }
+
/* Read in the code area. */
j = code_section_array[i].code_section_index;
- elf_object_read(section_header[j].elf_section_header_offset, code_buffer, code_section_array[i].code_section_size);
+ if (elf_object_read(section_header[j].elf_section_header_offset, code_buffer, code_section_array[i].code_section_size) != 0)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: read failed on a code section **** \n");
+
+ /* Release the code section buffer, then close the files and release
+ the ELF areas. */
+ free(code_buffer);
+ converter_cleanup();
+
+ return(6);
+ }
/* Write out the contents of this program area. */
size = code_section_array[i].code_section_size;
@@ -333,11 +524,14 @@ unsigned char zero_value;
/* Move index into buffer. */
j++;
}
+
+ /* Release the code section buffer before the next section is read. */
+ free(code_buffer);
+ code_buffer = NULL;
}
- /* Close files. */
- fclose(source_file);
- fclose(binary_file);
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
return 0;
}
diff --git a/common_modules/module_manager/utilities/module_to_c_array.c b/common_modules/module_manager/utilities/module_to_c_array.c
index d3472416..72e87de0 100644
--- a/common_modules/module_manager/utilities/module_to_c_array.c
+++ b/common_modules/module_manager/utilities/module_to_c_array.c
@@ -9,11 +9,25 @@
/* SPDX-License-Identifier: MIT */
/***************************************************************************/
+// Portions of this file were generated with AI assistance.
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+/* MISRA C:2012 Rule 21.3 and Dir 4.12 deviation: dynamic memory is used in this
+ file. This is a host-side conversion utility executed on the development
+ machine, not ThreadX runtime code, and the ELF areas being read have sizes
+ that are only known at run time. Every allocation result is checked for NULL
+ and every buffer is released before its pointer is reused. */
+
+/* MISRA C:2012 Rule 15.5 (advisory) deviation: main() returns from several
+ error paths instead of having a single point of exit. The project forbids
+ goto, so an early return is the only way to abandon the conversion, and this
+ matches the style already used by the parameter and file open checks. */
+
+
/* Define the file handles. */
FILE *source_file;
@@ -137,13 +151,52 @@ unsigned char *buffer;
}
+/* Close the files and release the ELF areas allocated by main(). This is called
+ from every exit path taken after the files have been opened, so it must
+ tolerate being called with resources that were never acquired. The areas it
+ releases are the file scope pointers declared above. */
+
+static void converter_cleanup(void)
+{
+
+ /* Determine if the source file is open. */
+ if (source_file != NULL)
+ {
+
+ /* Close it. */
+ fclose(source_file);
+ source_file = NULL;
+ }
+
+ /* Determine if the C array output file is open. */
+ if (array_file != NULL)
+ {
+
+ /* Close it. */
+ fclose(array_file);
+ array_file = NULL;
+ }
+
+ /* Release the ELF areas. Note that free() is defined to do nothing when it
+ is supplied a NULL pointer, so no test is required here. */
+ free(program_header);
+ program_header = NULL;
+ free(section_header);
+ section_header = NULL;
+ free(section_string_table);
+ section_string_table = NULL;
+ free(code_section_array);
+ code_section_array = NULL;
+}
+
+
int main(int argc, char* argv[])
{
unsigned long i, j, k;
-unsigned long current_total;
unsigned long address;
unsigned long size;
+unsigned long allocation_size;
unsigned long column;
unsigned char *code_buffer;
unsigned long code_section_index;
@@ -155,8 +208,11 @@ CODE_SECTION_ENTRY code_section_temp;
{
/* Print an error message out and wait for user key hit. */
- printf("module_to_c_array.exe - Copyright (c) Microsoft Corporation v5.8\n");
- printf("**** Error: invalid input parameter for module_to_c_array.exe **** \n");
+ printf("module_to_c_array\n");
+ printf("(c) 2024 Microsoft Corp\n");
+ printf("(c) 2026 Eclipse ThreadX contributors\n");
+ printf("v6.5.2.202603\n");
+ printf("**** Error: invalid input parameter for module_to_c_array **** \n");
printf(" Command Line Should be:\n\n");
printf(" > module_to_c_array source_elf_file c_array_file <cr> \n\n");
return(1);
@@ -189,11 +245,23 @@ CODE_SECTION_ENTRY code_section_temp;
}
/* Read the ELF header. */
- elf_object_read(0, &header, sizeof(header));
+ if (elf_object_read(0, &header, sizeof(header)) != 0)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: read failed on the ELF header **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(6);
+ }
fprintf(array_file, "/**************************** Module-to-C-array Utility *****************************************/\n");
fprintf(array_file, "/* */\n");
- fprintf(array_file, "/* Copyright (c) Microsoft Corporation Version 5.8, build date: 03-01-2018 */\n");
+ fprintf(array_file, "/* Copyright (c) 2024 Microsoft Corp */\n");
+ fprintf(array_file, "/* Copyright (c) 2026 Eclipse ThreadX contributors */\n");
+ fprintf(array_file, "/* v6.5.2.202603 */\n");
fprintf(array_file, "/* */\n");
fprintf(array_file, "/************************************************************************************************/\n\n");
fprintf(array_file, "/* \n");
@@ -202,26 +270,127 @@ CODE_SECTION_ENTRY code_section_temp;
fprintf(array_file, "*/\n\n");
/* Allocate memory for the program header(s). */
- program_header = malloc(sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries);
+ allocation_size = sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries;
+ program_header = malloc(allocation_size);
+
+ /* Determine if the memory allocation was successful. Note that an empty area
+ is not an error, since malloc() is permitted to return NULL for it. */
+ if ((program_header == NULL) && (allocation_size != 0))
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: memory allocation failed for the program header(s) **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(5);
+ }
/* Read the program header(s). */
- elf_object_read(header.elf_header_program_header_offset, program_header, (sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries));
+ if (elf_object_read(header.elf_header_program_header_offset, program_header, allocation_size) != 0)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: read failed on the program header(s) **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(6);
+ }
/* Allocate memory for the section header(s). */
- section_header = malloc(sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries);
+ allocation_size = sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries;
+ section_header = malloc(allocation_size);
+
+ /* Determine if the memory allocation was successful. */
+ if ((section_header == NULL) && (allocation_size != 0))
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: memory allocation failed for the section header(s) **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(5);
+ }
/* Read the section header(s). */
- elf_object_read(header.elf_header_section_header_offset, section_header, (sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries));
+ if (elf_object_read(header.elf_header_section_header_offset, section_header, allocation_size) != 0)
+ {
+ /* Print an error message out. */
+ printf("**** Error: read failed on the section header(s) **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(6);
+ }
+
+ /* Determine if the section string table index supplied by the ELF header is
+ inside the section header area that was just read. */
+ if (header.elf_header_section_string_index >= header.elf_header_section_header_entries)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: invalid section string table index in the ELF header **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(6);
+ }
/* Alocate memory for the section string table. */
- section_string_table = malloc(section_header[header.elf_header_section_string_index].elf_section_header_size);
+ allocation_size = section_header[header.elf_header_section_string_index].elf_section_header_size;
+ section_string_table = malloc(allocation_size);
+
+ /* Determine if the memory allocation was successful. */
+ if ((section_string_table == NULL) && (allocation_size != 0))
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: memory allocation failed for the section string table **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(5);
+ }
/* Read the section string table. */
- elf_object_read(section_header[header.elf_header_section_string_index].elf_section_header_offset, section_string_table, section_header[header.elf_header_section_string_index].elf_section_header_size);
+ if (elf_object_read(section_header[header.elf_header_section_string_index].elf_section_header_offset, section_string_table, allocation_size) != 0)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: read failed on the section string table **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(6);
+ }
/* Allocate memory for the code section array. */
- code_section_array = malloc(sizeof(CODE_SECTION_ENTRY)*header.elf_header_section_header_entries);
+ allocation_size = sizeof(CODE_SECTION_ENTRY)*header.elf_header_section_header_entries;
+ code_section_array = malloc(allocation_size);
+
+ /* Determine if the memory allocation was successful. */
+ if ((code_section_array == NULL) && (allocation_size != 0))
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: memory allocation failed for the code section array **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(5);
+ }
+
code_section_index = 0;
/* Print out the section header(s). */
@@ -272,9 +441,8 @@ CODE_SECTION_ENTRY code_section_temp;
fprintf(array_file, "unsigned char module_code[] = {0x00};\n\n");
- /* Close files. */
- fclose(source_file);
- fclose(array_file);
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
return(4);
}
@@ -321,7 +489,7 @@ CODE_SECTION_ENTRY code_section_temp;
/* Print out a character with a leading comma, except on the first character. */
if (column == 0)
- fprintf(array_file, "/* 0x%08X */ 0x00", address);
+ fprintf(array_file, "/* 0x%08lX */ 0x00", address);
else
fprintf(array_file, ", 0x00");
@@ -342,9 +510,34 @@ CODE_SECTION_ENTRY code_section_temp;
/* Now allocate memory for the code section. */
code_buffer = malloc(code_section_array[i].code_section_size);
+ /* Determine if the memory allocation was successful. */
+ if (code_buffer == NULL)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: memory allocation failed for code section **** \n");
+
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
+
+ return(5);
+ }
+
/* Read in the code area. */
j = code_section_array[i].code_section_index;
- elf_object_read(section_header[j].elf_section_header_offset, code_buffer, code_section_array[i].code_section_size);
+ if (elf_object_read(section_header[j].elf_section_header_offset, code_buffer, code_section_array[i].code_section_size) != 0)
+ {
+
+ /* Print an error message out. */
+ printf("**** Error: read failed on a code section **** \n");
+
+ /* Release the code section buffer, then close the files and release
+ the ELF areas. */
+ free(code_buffer);
+ converter_cleanup();
+
+ return(6);
+ }
/* Write out the contents of this program area. */
size = code_section_array[i].code_section_size;
@@ -356,7 +549,7 @@ CODE_SECTION_ENTRY code_section_temp;
/* Print out a character with a leading comma, except on the first character. */
if (column == 0)
- fprintf(array_file, "/* 0x%08X */ 0x%02X", address, (unsigned int) code_buffer[j]);
+ fprintf(array_file, "/* 0x%08lX */ 0x%02X", address, (unsigned int) code_buffer[j]);
else
fprintf(array_file, ", 0x%02X", (unsigned int) code_buffer[j]);
@@ -390,14 +583,17 @@ CODE_SECTION_ENTRY code_section_temp;
/* Move index into buffer. */
j++;
}
+
+ /* Release the code section buffer before the next section is read. */
+ free(code_buffer);
+ code_buffer = NULL;
}
/* Finally, finish the C array containing the module code. */
fprintf(array_file, "};\n\n");
- /* Close files. */
- fclose(source_file);
- fclose(array_file);
+ /* Close the files and release the ELF areas. */
+ converter_cleanup();
return 0;
}