NVC0_Firmware.mdwn 4.42 KB
Newer Older
1 2 3 4 5
# Firmware


## Status

Joe Rayhawk's avatar
Joe Rayhawk committed
6
[[A list of which cards do and don't need to load blob firmware at this point.|InstallDRM]]
7 8 9 10


## Instructions

Joe Rayhawk's avatar
Joe Rayhawk committed
11
do an [[MmioTrace]] of the blob (version < 270.xx preferred)
12

Joe Rayhawk's avatar
Joe Rayhawk committed
13
* Ensure that your kernel has MMIO tracing enabled
14

Joe Rayhawk's avatar
Joe Rayhawk committed
15
    Kernel Hacking -> Tracers -> Memory mapped IO tracing
16

Joe Rayhawk's avatar
Joe Rayhawk committed
17 18
* Boot up the system, without loading the blob or nouveau
* Mount debugfs and start the tracer
19

Joe Rayhawk's avatar
Joe Rayhawk committed
20 21 22
    mount -t debugfs debugfs /sys/kernel/debug
    echo mmiotrace > /sys/kernel/debug/tracing/current_tracer
    cat /sys/kernel/debug/tracing/trace_pipe > mydump.txt &
23

Joe Rayhawk's avatar
Joe Rayhawk committed
24 25 26
* Load the blob kernel module (insmod nvidia)
* run X or a CUDA application
* Stop the tracer
27

Joe Rayhawk's avatar
Joe Rayhawk committed
28
    echo nop > /sys/kernel/debug/tracing/current_tracer
29

Joe Rayhawk's avatar
Joe Rayhawk committed
30
Extract register writes from the trace and put them in binary files:
31

Joe Rayhawk's avatar
Joe Rayhawk committed
32 33 34 35 36
* 41a1c4 -> fuc41ad
* 4091c4 -> fuc409d
* 41a184 -> fuc41ac
* 409184 -> fuc409c
The important lines in the trace will look like this:
37

Joe Rayhawk's avatar
Joe Rayhawk committed
38
    W 4 433.851950 1 0xXX41a1c4 0x2072614d 0x0 0
39

Joe Rayhawk's avatar
Joe Rayhawk committed
40
where 0xXX41a1c4 is the register and 0x2072614d the value written
41

Joe Rayhawk's avatar
Joe Rayhawk committed
42
and put them in binary files in /lib/firmware/nouveau/
43

Joe Rayhawk's avatar
Joe Rayhawk committed
44
For Kepler, prefix the file names with "nvXX_", XX being the chipset id (so, nve4_fuc409c, for example).
45

Joe Rayhawk's avatar
Joe Rayhawk committed
46 47
    #!/usr/bin/python
    import struct, sys, re
48

Joe Rayhawk's avatar
Joe Rayhawk committed
49 50 51 52 53 54 55
    # substitute the correct value for XX
    registers = {
      'XX41a1c4': 'fuc41ad',
      'XX4091c4': 'fuc409d',
      'XX41a184': 'fuc41ac',
      'XX409184': 'fuc409c',
    }
56

Joe Rayhawk's avatar
Joe Rayhawk committed
57
    firmwares = dict((register, open(registers[register], 'wb')) for register in registers)
58

Joe Rayhawk's avatar
Joe Rayhawk committed
59 60 61 62 63 64 65
    for line in open(sys.argv[1]):
      line = line.split()
      if len(line) < 5:
        continue
      for register in registers:
        if not re.match(r'0x%s' % register, line[4]):
          continue
66

Joe Rayhawk's avatar
Joe Rayhawk committed
67 68
        if not line[5].startswith('0x'):
          break
69

Joe Rayhawk's avatar
Joe Rayhawk committed
70
        firmwares[register].write(struct.pack('@I', int(line[5][2:], 16)))
71 72 73

---

Joe Rayhawk's avatar
Joe Rayhawk committed
74 75 76 77 78 79 80 81 82 83 84 85 86 87

# Video firmware

Unlike the firmware you need above, there is no requirement on version. Up to nvidia 310.* will likely work. Newer versions are untested, but should still work.


## Extracting kernel video firmware on fermi and kepler.

There are 2 sets of firmware for video decoding, one for kernel and one for userspace. Only nvc0 series need the userspace firmware. Kepler, and also nvd9 do **NOT** have userspace firmware.

The kernel parts can be obtained by doing a mmiotrace of a program using vdpau for video decoding, for example mplayer -vc ffmpeg12vdpau,ffh264vdpau,ffwmv3vdpau,ffvc1vdpau,ffodivxvdpau, somefile.mkv

After you obtained the mmiotrace, look for the base offsets used by the firmware:

mperes's avatar
mperes committed
88
    $ demmio -f vdpau-mmiotrace | grep P.*P.*XFER_EXT_BASE
Joe Rayhawk's avatar
Joe Rayhawk committed
89 90 91 92
    [0] 437.753081 MMIO32 W 0x084110 0x004de400 PBSP.XFER_EXT_BASE <= 0x4de40000
    [0] 445.278672 MMIO32 W 0x085110 0x004dde00 PVP.XFER_EXT_BASE <= 0x4dde0000
    [0] 445.938745 MMIO32 W 0x086110 0x004dd800 PPPP.XFER_EXT_BASE <= 0x4dd80000

mperes's avatar
mperes committed
93
    $ demmio -f vdpau-mmiotrace | less
mperes's avatar
mperes committed
94 95 96
    /RAMIN32.*4de40000

would get you to the start of the mmiotrace, from my log I could see the RAMIN32 writes end at 4de50918, so I need to grab 4de[45].* for BSP firmware:
Joe Rayhawk's avatar
Joe Rayhawk committed
97

mperes's avatar
mperes committed
98
    $ demmio -f vdpau-mmiotrace 2>&1 | grep 'RAMIN32 .* 4de[45].* <=' | awk '{ print $7 }' | python -c \
Joe Rayhawk's avatar
Joe Rayhawk committed
99 100 101 102 103 104
    "
    import struct; import sys; fd = open(\"fuc084\", \"wb\");
    for line in sys.stdin:
            fd.write(struct.pack(\"@I\", int(line.rstrip(), 16)))
    "

mperes's avatar
mperes committed
105 106
Alternatively, you can use perl to execute for the last command. It is also more convenient as the same script can be used for all firmwares: 

mperes's avatar
mperes committed
107
    $ demmio -f vdpau-mmiotrace | grep 'RAMIN32 .* 4de[45].* <=' | awk '{ print $7 }' | perl -ne 'print pack "I", hex($_)' > fuc084
mperes's avatar
mperes committed
108

Joe Rayhawk's avatar
Joe Rayhawk committed
109 110 111 112 113
This was just for PBSP, but the same applies to PVP with fuc085, and PPPP with fuc086. Put the resulting files in /lib/firmware/nouveau/

Offsets may differ, and it is recommended to check you don't end up with too big or too small a file. It *looks* like mine are multiples of 1000 bytes, on the nvidia 310 drivers.

---
114 115 116 117


## Extracting userspace video firmware on nvc0 series (fermi) (NOT NVD9!!)

Joe Rayhawk's avatar
Joe Rayhawk committed
118
Requirements:
119

Joe Rayhawk's avatar
Joe Rayhawk committed
120 121 122 123 124 125
* libvdpau-dev, libpciaccess-dev, libx11-dev
* [[Valgrind-mmt]]
* build a recent envytools.git, and go to envytools.git/vdpow directory
* with nvidia drivers enabled and X server running, do:
* ` /usr/local/bin/valgrind --tool=mmt --mmt-trace-file=/dev/nvidia0 --mmt-trace-file=/dev/dri/card0 --mmt-trace-nvidia-ioctls --mmt-trace-nouveau-ioctls ./mmt_ufw 2>&1 | ./dumpstruct -m 10 `
Copy the resulting vuc-* files to /lib/firmware/nouveau/