@@ -186,3 +186,60 @@ int32_t pmp_init_kernel(pmp_config_t *config)
186186{
187187 return pmp_init_pools (config , kernel_mempools , KERNEL_MEMPOOL_COUNT );
188188}
189+
190+ int32_t pmp_set_region (pmp_config_t * config , const pmp_region_t * region )
191+ {
192+ if (!config || !region )
193+ return ERR_PMP_INVALID_REGION ;
194+
195+ /* Validate region index is within bounds */
196+ if (region -> region_id >= PMP_MAX_REGIONS )
197+ return ERR_PMP_INVALID_REGION ;
198+
199+ /* Validate address range */
200+ if (region -> addr_start >= region -> addr_end )
201+ return ERR_PMP_ADDR_RANGE ;
202+
203+ /* Check if region is already locked */
204+ if (config -> regions [region -> region_id ].locked )
205+ return ERR_PMP_LOCKED ;
206+
207+ uint8_t region_idx = region -> region_id ;
208+ uint8_t pmpcfg_idx = region_idx / 4 ;
209+ uint8_t pmpcfg_offset = (region_idx % 4 ) * 8 ;
210+
211+ /* Build configuration byte with TOR mode and permissions */
212+ uint8_t pmpcfg_perm = region -> permissions & (PMPCFG_R | PMPCFG_W | PMPCFG_X );
213+ uint8_t pmpcfg_byte = PMPCFG_A_TOR | pmpcfg_perm ;
214+ if (region -> locked )
215+ pmpcfg_byte |= PMPCFG_L ;
216+
217+ /* Read current pmpcfg register to preserve other regions */
218+ uint32_t pmpcfg_val = read_pmpcfg (pmpcfg_idx );
219+
220+ /* Clear the configuration byte for this region */
221+ pmpcfg_val &= ~(0xFFU << pmpcfg_offset );
222+
223+ /* Write new configuration byte */
224+ pmpcfg_val |= (pmpcfg_byte << pmpcfg_offset );
225+
226+ /* Write pmpaddr register with the upper boundary */
227+ write_pmpaddr (region_idx , region -> addr_end );
228+
229+ /* Write pmpcfg register with updated configuration */
230+ write_pmpcfg (pmpcfg_idx , pmpcfg_val );
231+
232+ /* Update shadow configuration */
233+ config -> regions [region_idx ].addr_start = region -> addr_start ;
234+ config -> regions [region_idx ].addr_end = region -> addr_end ;
235+ config -> regions [region_idx ].permissions = region -> permissions ;
236+ config -> regions [region_idx ].priority = region -> priority ;
237+ config -> regions [region_idx ].region_id = region_idx ;
238+ config -> regions [region_idx ].locked = region -> locked ;
239+
240+ /* Update region count if this is a newly used region */
241+ if (region_idx >= config -> region_count )
242+ config -> region_count = region_idx + 1 ;
243+
244+ return ERR_OK ;
245+ }
0 commit comments