static int mmio_read_x(int argc, const char *argv[], const struct cmd_info *info) { int ret; data_store data; struct mmap_info mmap_addr; const struct mmap_file_flags *mmf; mmf = info->privdata; mmap_addr.addr = strtoull(argv[1], NULL, 0); if (open_mapping(&mmap_addr, O_RDONLY | mmf->flags, sizeof(data)) < 0) { return -1; } ret = 0; #define DO_READ(mem_, off_, size_)\ data.u ##size_ = *(typeof(data.u ##size_) *)(mem_ + off_); \ fprintf(stdout, "0x%0*llx\n", (int)sizeof(data.u ##size_)*2, \ (unsigned long long)data.u ##size_) switch (get_command_size(info)) { case SIZE8: DO_READ(mmap_addr.mem, mmap_addr.off, 8); break; case SIZE16: DO_READ(mmap_addr.mem, mmap_addr.off, 16); break; case SIZE32: DO_READ(mmap_addr.mem, mmap_addr.off, 32); break; case SIZE64: if (sizeof(void *) != sizeof(uint64_t)) { fprintf(stderr, "warning: 64 bit operations might " "not be atomic on 32 bit builds\n"); } DO_READ(mmap_addr.mem, mmap_addr.off, 64); break; default: fprintf(stderr, "invalid mmio_read parameter\n"); ret = -1; } close_mapping(&mmap_addr); return ret; }
static int mmio_write_x(int argc, const char *argv[], const struct cmd_info *info) { int ret; unsigned long ldata; data_store data; struct mmap_info mmap_addr; mmap_addr.addr = strtoull(argv[1], NULL, 0); ldata = strtoul(argv[2], NULL, 0); if (open_mapping(&mmap_addr, O_RDWR, sizeof(data)) < 0) { return -1; } ret = 0; #define DO_WRITE(mem_, off_, size_)\ data.u ##size_ = (typeof(data.u ##size_))ldata;\ *(typeof(data.u ##size_) *)(mem_+off_) = data.u ##size_ switch (get_command_size(info)) { case SIZE8: DO_WRITE(mmap_addr.mem, mmap_addr.off, 8); break; case SIZE16: DO_WRITE(mmap_addr.mem, mmap_addr.off, 16); break; case SIZE32: DO_WRITE(mmap_addr.mem, mmap_addr.off, 32); break; case SIZE64: if (sizeof(void *) != sizeof(uint64_t)) { fprintf(stderr, "warning: 64 bit operations might " "not be atomic on 32 bit builds\n"); } DO_WRITE(mmap_addr.mem, mmap_addr.off, 64); break; default: fprintf(stderr, "invalid mmio_write parameter\n"); ret = -1; } close_mapping(&mmap_addr); return ret; }
/* * DANG_BEGIN_FUNCTION low_mem_init * * description: * Initializes the lower 1Meg via mmap & sets up the HMA region * * DANG_END_FUNCTION */ void low_mem_init(void) { void *lowmem, *result; #ifdef __i386__ PRIV_SAVE_AREA #endif open_mapping(MAPPING_INIT_LOWRAM); g_printf ("DOS+HMA memory area being mapped in\n"); lowmem = alloc_mapping(MAPPING_INIT_LOWRAM, LOWMEM_SIZE + HMASIZE, -1); if (lowmem == MAP_FAILED) { perror("LOWRAM alloc"); leavedos(98); } #ifdef __i386__ /* we may need root to mmap address 0 */ enter_priv_on(); result = alias_mapping(MAPPING_INIT_LOWRAM, 0, LOWMEM_SIZE + HMASIZE, PROT_READ | PROT_WRITE | PROT_EXEC, lowmem); leave_priv_setting(); if (result == MAP_FAILED && (errno == EPERM || errno == EACCES)) { #ifndef X86_EMULATOR perror ("LOWRAM mmap"); fprintf(stderr, "Cannot map low DOS memory (the first 640k).\n" "You can most likely avoid this problem by running\n" "sysctl -w vm.mmap_min_addr=0\n" "as root, or by changing the vm.mmap_min_addr setting in\n" "/etc/sysctl.conf or a file in /etc/sysctl.d/ to 0.\n" "If this doesn't help, disable selinux in /etc/selinux/config\n" ); exit(EXIT_FAILURE); #else if (config.cpuemu < 3) { /* switch on vm86-only JIT CPU emulation to with non-zero base */ config.cpuemu = 3; init_emu_cpu(); c_printf("CONF: JIT CPUEMU set to 3 for %d86\n", (int)vm86s.cpu_type); error("Using CPU emulation because vm.mmap_min_addr > 0.\n" "You can most likely avoid this problem by running\n" "sysctl -w vm.mmap_min_addr=0\n" "as root, or by changing the vm.mmap_min_addr setting in\n" "/etc/sysctl.conf or a file in /etc/sysctl.d/ to 0.\n" "If this doesn't help, disable selinux in /etc/selinux/config\n" ); } result = alias_mapping(MAPPING_INIT_LOWRAM, -1, LOWMEM_SIZE + HMASIZE, PROT_READ | PROT_WRITE | PROT_EXEC, lowmem); #endif } #else result = alias_mapping(MAPPING_INIT_LOWRAM, -1, LOWMEM_SIZE + HMASIZE, PROT_READ | PROT_WRITE | PROT_EXEC, lowmem); if (config.cpuemu < 3) { /* switch on vm86-only JIT CPU emulation to with non-zero base */ config.cpuemu = 3; init_emu_cpu(); c_printf("CONF: JIT CPUEMU set to 3 for %d86\n", (int)vm86s.cpu_type); } #endif if (result == MAP_FAILED) { perror ("LOWRAM mmap"); exit(EXIT_FAILURE); } #ifdef X86_EMULATOR if (result) { warn("WARN: using non-zero memory base address %p.\n" "WARN: You can use the better-tested zero based setup using\n" "WARN: sysctl -w vm.mmap_min_addr=0\n" "WARN: as root, or by changing the vm.mmap_min_addr setting in\n" "WARN: /etc/sysctl.conf or a file in /etc/sysctl.d/ to 0.\n", result); } #endif /* keep conventional memory protected as long as possible to protect NULL pointer dereferences */ mprotect_mapping(MAPPING_LOWMEM, result, config.mem_size * 1024, PROT_NONE); }
static int mmio_dump(int argc, const char *argv[], const struct cmd_info *info) { unsigned long bytes_to_dump; unsigned long bytes_left; struct mmap_info mmap_addr; uint32_t *addr; uint64_t desired_addr; int fields_on_line; int write_binary; desired_addr = strtoull(argv[1], NULL, 0); bytes_to_dump = strtoul(argv[2], NULL, 0); write_binary = 0; if (argc == 4) { if (!strcmp(argv[3], "-b")) { write_binary = 1; } else { return -1; } } mmap_addr.addr = desired_addr; if (open_mapping(&mmap_addr, O_RDONLY, bytes_to_dump) < 0) { return -1; } if (write_binary) { void *buffer_to_write = (void *)mmap_addr.mem + mmap_addr.off; int ret = fwrite(buffer_to_write, bytes_to_dump, 1, stdout); close_mapping(&mmap_addr); return ret == 1 ? 0 : -1; } addr = (void *)mmap_addr.mem + mmap_addr.off; bytes_left = bytes_to_dump; fields_on_line = 0; while (bytes_left) { int bytes_printed = sizeof(*addr); /* Print out the current address. */ if (!fields_on_line) { fprintf(stdout, "0x%016llx:", (unsigned long long)desired_addr); } /* Print out the leftover bytes. */ if (bytes_left < sizeof(*addr)) { unsigned char *ptr = (unsigned char *)addr; fprintf(stdout, " 0x%02x", *ptr); /* Adjust the working pointer and the bytes_printed */ addr = (typeof(addr))++ptr; bytes_printed = sizeof(*ptr); } else { fprintf(stdout, " 0x%08x", *addr); addr++; } /* Keep track of statistics. */ bytes_left -= bytes_printed; desired_addr += bytes_printed; /* Default to printing out 4 sets of 32-bit values. */ fields_on_line = (fields_on_line + 1) % 4; /* Handle the new line once we are field 0 again. */ if (!fields_on_line) { fprintf(stdout, "\n"); } } /* Print newline if we stopped printing in the middle of a line. */ if (fields_on_line) { fprintf(stdout, "\n"); } close_mapping(&mmap_addr); return 0; }