@@ -264,3 +264,61 @@ int32_t pmp_init_kernel(pmp_config_t *config)
264264{
265265 return pmp_init_pools (config , kernel_mempools , KERNEL_MEMPOOL_COUNT );
266266}
267+
268+ int32_t pmp_set_region (pmp_config_t * config , const pmp_region_t * region )
269+ {
270+ if (!config || !region )
271+ return ERR_PMP_INVALID_REGION ;
272+
273+ /* Validate region index is within bounds */
274+ if (region -> region_id >= PMP_MAX_REGIONS )
275+ return ERR_PMP_INVALID_REGION ;
276+
277+ /* Validate address range */
278+ if (region -> addr_start >= region -> addr_end )
279+ return ERR_PMP_ADDR_RANGE ;
280+
281+ /* Check if region is already locked */
282+ if (config -> regions [region -> region_id ].locked )
283+ return ERR_PMP_LOCKED ;
284+
285+ uint8_t region_idx = region -> region_id ;
286+ uint8_t pmpcfg_idx = region_idx / 4 ;
287+ uint8_t pmpcfg_offset = (region_idx % 4 ) * 8 ;
288+
289+ /* Build configuration byte with TOR mode and permissions */
290+ uint8_t pmpcfg_perm =
291+ region -> permissions & (PMPCFG_R | PMPCFG_W | PMPCFG_X );
292+ uint8_t pmpcfg_byte = PMPCFG_A_TOR | pmpcfg_perm ;
293+ if (region -> locked )
294+ pmpcfg_byte |= PMPCFG_L ;
295+
296+ /* Read current pmpcfg register to preserve other regions */
297+ uint32_t pmpcfg_val = read_pmpcfg (pmpcfg_idx );
298+
299+ /* Clear the configuration byte for this region */
300+ pmpcfg_val &= ~(0xFFU << pmpcfg_offset );
301+
302+ /* Write new configuration byte */
303+ pmpcfg_val |= (pmpcfg_byte << pmpcfg_offset );
304+
305+ /* Write pmpaddr register with the upper boundary */
306+ write_pmpaddr (region_idx , region -> addr_end );
307+
308+ /* Write pmpcfg register with updated configuration */
309+ write_pmpcfg (pmpcfg_idx , pmpcfg_val );
310+
311+ /* Update shadow configuration */
312+ config -> regions [region_idx ].addr_start = region -> addr_start ;
313+ config -> regions [region_idx ].addr_end = region -> addr_end ;
314+ config -> regions [region_idx ].permissions = region -> permissions ;
315+ config -> regions [region_idx ].priority = region -> priority ;
316+ config -> regions [region_idx ].region_id = region_idx ;
317+ config -> regions [region_idx ].locked = region -> locked ;
318+
319+ /* Update region count if this is a newly used region */
320+ if (region_idx >= config -> region_count )
321+ config -> region_count = region_idx + 1 ;
322+
323+ return ERR_OK ;
324+ }
0 commit comments