Serenity Operating System
at master 108 lines 3.1 kB view raw
1/* 2 * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Types.h> 8#include <LibTest/TestCase.h> 9#include <assert.h> 10#include <errno.h> 11#include <fcntl.h> 12#include <inttypes.h> 13#include <stdio.h> 14#include <string.h> 15#include <sys/mman.h> 16#include <sys/stat.h> 17#include <unistd.h> 18 19static u8 read_buffer[0x100000]; 20 21static ALWAYS_INLINE bool mem_chunk(int fd, u64 base, u64 length) 22{ 23 u64 mmoffset = base % sysconf(_SC_PAGESIZE); 24 void* mmp = mmap(NULL, mmoffset + length, PROT_READ, MAP_SHARED, fd, base - mmoffset); 25 if (mmp == MAP_FAILED) 26 return false; 27 if (munmap(mmp, mmoffset + length) < 0) 28 perror("munmap"); 29 return true; 30} 31 32enum class ReadResult { 33 SeekFailure, 34 ReadFailure, 35 ReadSuccess, 36}; 37 38static ALWAYS_INLINE ReadResult read_chunk(int fd, u64 base, u64 length) 39{ 40 VERIFY(length <= sizeof(read_buffer)); 41 auto rs = lseek(fd, base, SEEK_SET); 42 if (rs < 0) { 43 fprintf(stderr, "Couldn't seek to offset %" PRIi64 " while verifying: %s\n", base, strerror(errno)); 44 return ReadResult::SeekFailure; 45 } 46 if (read(fd, read_buffer, length) < 0) 47 return ReadResult::ReadFailure; 48 return ReadResult::ReadSuccess; 49} 50 51TEST_CASE(test_memory_access_device_read) 52{ 53 int rc = geteuid(); 54 EXPECT_EQ(rc, 0); 55 56 int fd = open("/dev/mem", O_RDONLY); 57 EXPECT(fd >= 0); 58 59 // FIXME: This is expected to work on QEMU machines (both 440FX and Q35), 60 // however, it will be much nicer to have some sort of a node in the ProcFS 61 // to expose physical memory ranges (e820 memory map). 62 63 auto read_result = read_chunk(fd, 0x0, 0x100000); 64 EXPECT_EQ(read_result, ReadResult::ReadFailure); 65 66 read_result = read_chunk(fd, 0xe0000, 0x100000 - 0xe0000); 67 EXPECT_EQ(read_result, ReadResult::ReadSuccess); 68 69 read_result = read_chunk(fd, 0x100000, 0x200000 - 0x100000); 70 EXPECT_EQ(read_result, ReadResult::ReadFailure); 71 72 read_result = read_chunk(fd, 0xf0000, 70000); 73 EXPECT_EQ(read_result, ReadResult::ReadFailure); 74 75 read_result = read_chunk(fd, 0xfffc0000, 16384); 76 EXPECT_EQ(read_result, ReadResult::ReadSuccess); 77 78 read_result = read_chunk(fd, 0xfffc0000, 0x100000); 79 EXPECT_EQ(read_result, ReadResult::ReadFailure); 80} 81 82TEST_CASE(test_memory_access_device_mmap) 83{ 84 int rc = geteuid(); 85 EXPECT_EQ(rc, 0); 86 87 int fd = open("/dev/mem", O_RDONLY); 88 EXPECT(fd >= 0); 89 90 // FIXME: This is expected to work on QEMU machines (both 440FX and Q35), 91 // however, it will be much nicer to have some sort of a node in the ProcFS 92 // to expose physical memory ranges (e820 memory map). 93 94 auto mmap_result = mem_chunk(fd, 0xe0000, 0x100000 - 0xe0000); 95 EXPECT_EQ(mmap_result, true); 96 97 mmap_result = mem_chunk(fd, 0x100000, 0x200000 - 0x100000); 98 EXPECT_EQ(mmap_result, false); 99 100 mmap_result = mem_chunk(fd, 0xf0000, 70000); 101 EXPECT_EQ(mmap_result, false); 102 103 mmap_result = mem_chunk(fd, 0xfffc0000, 16384); 104 EXPECT_EQ(mmap_result, true); 105 106 mmap_result = mem_chunk(fd, 0xfffc0000, 0x100000); 107 EXPECT_EQ(mmap_result, false); 108}