diff --git a/submissions/raissa-coelho/README.md b/submissions/raissa-coelho/README.md new file mode 100644 index 0000000..bf8b633 --- /dev/null +++ b/submissions/raissa-coelho/README.md @@ -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
+``` diff --git a/submissions/raissa-coelho/config.txt b/submissions/raissa-coelho/config.txt new file mode 100644 index 0000000..32d235e --- /dev/null +++ b/submissions/raissa-coelho/config.txt @@ -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 \ No newline at end of file diff --git a/submissions/raissa-coelho/pmp.py b/submissions/raissa-coelho/pmp.py new file mode 100644 index 0000000..7283f52 --- /dev/null +++ b/submissions/raissa-coelho/pmp.py @@ -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() \ No newline at end of file