Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions submissions/raissa-coelho/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

# PMP

Made by Raíssa Coelho
Python version: 3.13.0

## Project Description

This project is a solution to the IDL challenge.

## Usage

To run the project, use the following command:

```sh
python pmp.py <file_config> <address> <mode> <operation>
```
128 changes: 128 additions & 0 deletions submissions/raissa-coelho/config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
0x3A
0x7F
0x1C
0x9D
0x4E
0xB2
0x5F
0x8A
0x2B
0x6C
0xF1
0x0D
0xE4
0x59
0x3B
0xA7
0x8E
0x42
0x6D
0xC9
0x1F
0x7A
0x5B
0x0E
0x93
0x2D
0x4A
0x8C
0x6F
0xB5
0x1A
0x3E
0x7D
0x0F
0x9B
0x2C
0x5A
0x8D
0xE7
0x4B
0x6A
0x1E
0x3D
0x7C
0x0A
0x9F
0x2E
0x5C
0x8B
0xE1
0x4D
0x6E
0x1B
0x3F
0x7E
0x0C
0x9A
0x2F
0x5D
0x89
0xE3
0x4F
0x6B
0x1D
0x1A
0x3F7
0xB2C
0x4DF9
0x7E
0x1F8A
0x5C3
0x9D4
0x2EB
0x6A1F
0x3D
0x8C7
0x1B5
0x4E2
0x7F9A
0x2C
0x5F3
0x9A8
0x1E7
0x3B4
0x6D
0x8F2
0x1C9
0x4A5
0x7B
0x2F8
0x5E6
0x9C1
0x1D3
0x3A
0x6F4
0x8D
0x1E2
0x4B9
0x7C5
0x2A
0x5D7
0x9E
0x1F
0x3C8
0x6B
0x8A
0x1D5
0x4E
0x7F
0x2B3
0x5C
0x9F
0x1A2
0x3E
0x6D4
0x8B
0x1C
0x4F
0x7A
0x2D
0x5E
0x9B
0x1F3
0x3A5
0x6C
0x8E
0x1D6
0x4B
157 changes: 157 additions & 0 deletions submissions/raissa-coelho/pmp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
## Made By Raíssa Coelho

import argparse

"""read_config reads the PMP configuration file
Args:
path: path to the PMP configuration file
Returns:
pmpcfg: PMP configuration bits
"""
def read_config(path):
pmpcfg = []
pmpaddr = []

with open(path, "r") as file:
for _ in range(64):
pmpcfg.append(bin(int(file.readline().strip(), 16))[2:].zfill(8))

for _ in range(64):
pmpaddr.append(file.readline().strip())

return pmpcfg, pmpaddr


"""check_pmpcfg checks the PMP configuration bits
Args:
pmcfg: PMP configuration bits
Returns:
L: locked region
A: address-matching mode
X: execute permission
W: write permission
R: read permission
"""
def check_pmpcfg(pmcfg):
L = pmcfg[0]
A = pmcfg[3:5]
X = pmcfg[5]
W = pmcfg[6]
R = pmcfg[7]

return L, A, X, W, R

"""check_permission checks if the access is granted
or denied based on the mode and the permission bits
"""
def check_permission(mode, op, R, W, X):
if mode == "M":
print(f'Access granted.')
elif mode == "S" or mode == "U":
if op == "R" and R == "0":
print(f'Access denied.')
elif op == "W" and W == "0":
print(f'Access denied.')
elif op == "X" and X == "0":
print(f'Access denied.')
else:
print(f'Access granted.')

"""pmp checks the PMP configuration and address
Args:
pmpcfg: PMP configuration
pmpaddr: PMP address
physical_addr: physical address
mode: privilege mode - M, S, U
op: operation: read,write,execute - R, W, X
"""
def pmp(pmpcfg, pmpaddr, physical_addr, mode, op):
physical_addr = int(physical_addr, 16)

addr = [int(a, 16) for a in pmpaddr]
for i in range(64):
L, A, X, W, R = check_pmpcfg(pmpcfg[i])

""" Locked region
"""
if int(L) == 1:
print(f'PMP region {i} is locked')
continue

""" Null region
"""
if A == "00":
if mode == "M":
print(f'Access granted.')
else:
print(f'Access denied.')

"""TOR - Top of range
Args:
addr: base address of the region
physical_addr: physical address
"""
if A == "01":
if i == 0:
continue
if addr[i - 1] <= physical_addr < addr[i]:
check_permission(mode, op, R, W, X)
else:
if mode == "M":
print(f'Access granted.')
elif mode == "S" or mode == "U":
print(f'Access denied.')

"""NA4 - Naturally aligned four-byte region
Args:
addr: base address of the region
physical_addr: physical address
"""
if A == "10":
if addr[i] <= physical_addr < addr[i] + 4:
check_permission(mode, op, R, W, X)
else:
if mode == "M":
print(f'Access granted.')
elif mode == "S" or mode == "U":
print(f'Access denied.')

"""NAPOT - Naturally aligned power-of-two region
Args:
napot: number of address bits to be used
size: size of the region
base: base address of the region
"""
if A == "11":
napot = addr[i] ^ (addr[i] + 1)
size = napot + 1

base = addr[i] & ~(size - 1)
if base <= physical_addr < base + size:
check_permission(mode, op, R, W, X)
else:
if mode == "M":
print(f'Access granted.')
elif mode == "S" or mode == "U":
print(f'Access denied.')
def main():
parser = argparse.ArgumentParser(description='Verify acess.')

"""Arguments:
path: pmp_configuration file
addr: physical address in hexadecimal
mode: privilege mode
op: operation: read,write,execute/fetch
"""
parser.add_argument('path', type=str, help='pmp_configuration file')
parser.add_argument('addr', type=str, help='physical address in hexadecimal')
parser.add_argument('mode', type=str, help='privilege mode')
parser.add_argument('op', type=str, help='operation: read,write,execute/fetch')

args = parser.parse_args()
pmpcfg, pmpaddr = read_config(args.path)

pmp(pmpcfg, pmpaddr, args.addr, args.mode, args.op)

if __name__ == '__main__':
main()