1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** USBX Component */
16 /** */
17 /** USBX main stack */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 /* Include necessary system files. */
24
25 #define UX_SOURCE_CODE
26
27 #include "ux_api.h"
28
29
30 /**************************************************************************/
31 /* */
32 /* FUNCTION RELEASE */
33 /* */
34 /* _ux_utility_memory_byte_pool_create PORTABLE C */
35 /* 6.3.0 */
36 /* AUTHOR */
37 /* */
38 /* Yajun Xia, Microsoft Corporation */
39 /* */
40 /* DESCRIPTION */
41 /* */
42 /* This function creates a pool of memory bytes in the specified */
43 /* memory area. */
44 /* */
45 /* INPUT */
46 /* */
47 /* pool_ptr Pointer to pool control block */
48 /* pool_start Address of beginning of pool area */
49 /* pool_size Number of bytes in the byte pool */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* UX_SUCCESS Successful completion status */
54 /* */
55 /* CALLS */
56 /* */
57 /* None */
58 /* */
59 /* CALLED BY */
60 /* */
61 /* USBX Components */
62 /* */
63 /* RELEASE HISTORY */
64 /* */
65 /* DATE NAME DESCRIPTION */
66 /* */
67 /* 10-31-2023 Yajun Xia Initial Version 6.3.0 */
68 /* */
69 /**************************************************************************/
_ux_utility_memory_byte_pool_create(UX_MEMORY_BYTE_POOL * pool_ptr,VOID * pool_start,ULONG pool_size)70 UINT _ux_utility_memory_byte_pool_create(UX_MEMORY_BYTE_POOL *pool_ptr, VOID *pool_start, ULONG pool_size)
71 {
72
73 UCHAR *block_ptr;
74 UCHAR **block_indirect_ptr;
75 UCHAR *temp_ptr;
76 ALIGN_TYPE *free_ptr;
77
78
79 /* Initialize the byte pool control block to all zeros. */
80 _ux_utility_memory_set((UCHAR *)pool_ptr, 0, sizeof(UX_MEMORY_BYTE_POOL)); /* Use case of memset is verified. */
81
82 /* Round the pool size down to something that is evenly divisible by
83 an ULONG. */
84 pool_size = (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
85
86 /* Save the start and size of the pool. */
87 pool_ptr -> ux_byte_pool_start = UX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
88 pool_ptr -> ux_byte_pool_size = pool_size;
89 pool_ptr -> ux_byte_pool_search = UX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
90
91 /* Initially, the pool will have two blocks. One large block at the
92 beginning that is available and a small allocated block at the end
93 of the pool that is there just for the algorithm. Be sure to count
94 the available block's header in the available bytes count. */
95 pool_ptr -> ux_byte_pool_available = pool_size - ((sizeof(VOID *)) + (sizeof(ALIGN_TYPE)));
96 pool_ptr -> ux_byte_pool_fragments = ((UINT) 2);
97
98 /* Each block contains a "next" pointer that points to the next block in the pool followed by a ALIGN_TYPE
99 field that contains either the constant UX_BYTE_BLOCK_FREE (if the block is free) or a pointer to the
100 owning pool (if the block is allocated). */
101
102 /* Calculate the end of the pool's memory area. */
103 block_ptr = UX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
104 block_ptr = UX_UCHAR_POINTER_ADD(block_ptr, pool_size);
105
106 /* Backup the end of the pool pointer and build the pre-allocated block. */
107 block_ptr = UX_UCHAR_POINTER_SUB(block_ptr, (sizeof(ALIGN_TYPE)));
108
109 /* Cast the pool pointer into a ULONG. */
110 temp_ptr = UX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr);
111 block_indirect_ptr = UX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
112 *block_indirect_ptr = temp_ptr;
113
114 block_ptr = UX_UCHAR_POINTER_SUB(block_ptr, (sizeof(UCHAR *)));
115 block_indirect_ptr = UX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
116 *block_indirect_ptr = UX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
117
118 /* Now setup the large available block in the pool. */
119 temp_ptr = UX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
120 block_indirect_ptr = UX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(temp_ptr);
121 *block_indirect_ptr = block_ptr;
122 block_ptr = UX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
123 block_ptr = UX_UCHAR_POINTER_ADD(block_ptr, (sizeof(UCHAR *)));
124 free_ptr = UX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(block_ptr);
125 *free_ptr = UX_BYTE_BLOCK_FREE;
126
127 /* Return UX_SUCCESS. */
128 return(UX_SUCCESS);
129 }
130