diff --git a/submissions/Rupa-Rd/pmp_check.cpp b/submissions/Rupa-Rd/pmp_check.cpp new file mode 100644 index 0000000..4b05316 --- /dev/null +++ b/submissions/Rupa-Rd/pmp_check.cpp @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include +#include +#include + +const int PMP_ENTRIES = 64; + +struct PMPConfig { + uint8_t R : 1; + uint8_t W : 1; + uint8_t X : 1; + uint8_t A : 2; + uint8_t reserved : 2; + uint8_t L : 1; +}; + +struct PMPEntry { + PMPConfig config; + uint64_t address; +}; + +void parseArguments(int argc, char* argv[], std::string& configFile, uint64_t& address, char& mode, char& operation) { + if (argc != 5) { + throw std::invalid_argument("Usage: program
"); + } + + configFile = argv[1]; + + // Check if address starts with "0x" + std::string addrStr = argv[2]; + if (addrStr.size() < 2 || addrStr.substr(0, 2) != "0x") { + throw std::invalid_argument("Physical address must start with '0x'."); + } + address = std::stoull(addrStr, nullptr, 16); + + mode = argv[3][0]; + operation = argv[4][0]; + + if (mode != 'M' && mode != 'S' && mode != 'U') { + throw std::invalid_argument("Invalid privilege mode. Must be 'M', 'S', or 'U'."); + } + + if (operation != 'R' && operation != 'W' && operation != 'X') { + throw std::invalid_argument("Invalid operation. Must be 'R', 'W', or 'X'."); + } +} + +void readPMPConfig(const std::string& configFile, std::vector& pmpEntries) { + std::ifstream file(configFile); + if (!file.is_open()) { + throw std::runtime_error("Could not open PMP configuration file."); + } + + for (int i = 0; i < PMP_ENTRIES; ++i) { + std::string line; + if (!std::getline(file, line)) { + throw std::runtime_error("Invalid PMP configuration file format."); + } + + uint8_t configValue = std::stoul(line, nullptr, 16); + pmpEntries[i].config = *reinterpret_cast(&configValue); + } + + for (int i = 0; i < PMP_ENTRIES; ++i) { + std::string line; + if (!std::getline(file, line)) { + throw std::runtime_error("Invalid PMP configuration file format."); + } + + pmpEntries[i].address = std::stoull(line, nullptr, 16); + } +} + +bool checkPMPAccess(const std::vector& pmpEntries, uint64_t address, char mode, char operation) { + for (int i = 0; i < PMP_ENTRIES; ++i) { + const PMPEntry& entry = pmpEntries[i]; + + if (entry.config.A == 0) continue; // Skip disabled entries + + uint64_t lowerBound = 0; + uint64_t upperBound = 0; + + if (entry.config.A == 1) { // TOR mode + if (i == 0) { + lowerBound = 0; + } else { + lowerBound = pmpEntries[i - 1].address; + } + upperBound = entry.address; + } else if (entry.config.A == 2) { // NA4 mode + lowerBound = entry.address & ~0x3ULL; + upperBound = lowerBound + 4; + } else if (entry.config.A == 3) { // NAPOT mode + uint64_t mask = ~(entry.address | (entry.address - 1)); + lowerBound = entry.address & mask; + upperBound = lowerBound + (mask + 1); + } + + if (address >= lowerBound && address < upperBound) { + if (mode == 'M' && !entry.config.L) { + return true; // M-mode access succeeds if L bit is clear + } + + if (operation == 'R' && !entry.config.R) return false; + if (operation == 'W' && !entry.config.W) return false; + if (operation == 'X' && !entry.config.X) return false; + + return true; + } + } + + // If no PMP entry matches, M-mode access succeeds, S/U-mode access fails + return mode == 'M'; +} + +int main(int argc, char* argv[]) { + try { + std::string configFile; + uint64_t address; + char mode, operation; + + parseArguments(argc, argv, configFile, address, mode, operation); + + std::vector pmpEntries(PMP_ENTRIES); + readPMPConfig(configFile, pmpEntries); + + bool accessAllowed = checkPMPAccess(pmpEntries, address, mode, operation); + + std::cout << "Access " << (accessAllowed ? "allowed" : "denied") << std::endl; + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + + return 0; +} \ No newline at end of file diff --git a/submissions/Rupa-Rd/pmp_check.exe b/submissions/Rupa-Rd/pmp_check.exe new file mode 100644 index 0000000..4b453f2 Binary files /dev/null and b/submissions/Rupa-Rd/pmp_check.exe differ diff --git a/submissions/Rupa-Rd/pmp_configuration.txt b/submissions/Rupa-Rd/pmp_configuration.txt new file mode 100644 index 0000000..57affba --- /dev/null +++ b/submissions/Rupa-Rd/pmp_configuration.txt @@ -0,0 +1,128 @@ +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x07 +0x01 +0x03 +0x00 +0x1000 +0x2000 +0x3000 +0x4000 +0x5000 +0x6000 +0x7000 +0x8000 +0x9000 +0x10000 +0x11000 +0x12000 +0x13000 +0x14000 +0x15000 +0x16000 +0x17000 +0x18000 +0x19000 +0x20000 +0x21000 +0x22000 +0x23000 +0x24000 +0x25000 +0x26000 +0x27000 +0x28000 +0x29000 +0x30000 +0x31000 +0x32000 +0x33000 +0x34000 +0x35000 +0x36000 +0x37000 +0x38000 +0x39000 +0x40000 +0x41000 +0x42000 +0x43000 +0x44000 +0x45000 +0x46000 +0x47000 +0x48000 +0x49000 +0x50000 +0x51000 +0x52000 +0x53000 +0x54000 +0x55000 +0x56000 +0x57000 +0x58000 +0x59000 +0x60000 +0x61000 +0x62000 +0x63000 +0x64000 \ No newline at end of file