I've spent some time reversing how the bootloader tries to do this update. It turns out that "upgrade_info_7db780a713a4.txt" contains a bunch of u-boot commands which are executed in sequence (with a couple of extra lines at the beginning of the file).
The first line contains the crc32 of the rest of the file, while the second line contains a fixed string.
So the upgrade file looks like:
	
	
	
		Code:
	
	
		CRC:<crc32 (in decimal) of the rest of the file, starting from the next line>
MagicString:c016dcd6-cdeb-45df-9fd0-e821bf0e1e62
command1
command2
command3
...
	 
 
Note that u-boot does not check the 'CRC' and 'MagicString' labels (I made them up, you can put anything there), it just scans the line until it finds the ':', and whathever finds after that is the crc32 (1st line) or the magic string (2nd line).
The text file can use LF or CR/LF as line separators.
In case of failure (e.g. "upgrade_info_7db780a713a4.txt" not found, crc32 does not match, magic string does not match, etc.), the bootloader tries to transfer a file named "failed.txt", otherwise it tries to transfer a file named "success.txt". It does not seem to do anything with the content of the file (as a matter of facts, it also ignores if the transfer succeeds or fails).
The network configuration is based on the following environment variables (with the default value listed next to them):
Camera IP config:
autolip 192.168.1.108
autogw  192.168.1.1
autonm  255.255.255.0
TFTP server IP:
autosip 192.168.254.254
Note that the camera and the TFTP server are on different networks, so make sure to configure your network properly in order for the TFTP transfer to take place.
The following is simple python script to generate the "upgrade_info_7db780a713a4.txt" from a file containig a list of commands:
	
	
	
		Code:
	
	
		#!/usr/bin/env python
import zlib
import sys
input_file=sys.argv[1]
with open(input_file, 'rb') as cmdfile:
    data=cmdfile.read()
    checksumed_data = b'MagicString:c016dcd6-cdeb-45df-9fd0-e821bf0e1e62\n' + data
    crc = zlib.crc32(checksumed_data) & 0xffffffff
    crc_str = str(crc).encode("ascii")
    output_data = b'CRC:' + crc_str + b'\n' + checksumed_data
    with open("upgrade_info_7db780a713a4.txt", 'wb') as outfile:
        outfile.write(output_data)
	 
 
As a test, I created a simple command file which contains a ping to the TFTP server IP address. In this way, I can figure out if the command is effectively executed by u-boot by looking at the packet capture.
Text file with the command(s) to execute:
	
	
	
		Code:
	
	
		> cat commands.txt
ping 192.168.254.254
	 
 
Generate the corresponding "upgrade_info_7db780a713a4.txt":
	
	
	
		Code:
	
	
		> ./generate_upgrade_info.py commands.txt
	 
 
Resulting file:
	
	
	
		Code:
	
	
		> cat upgrade_info_7db780a713a4.txt
CRC:2819959008
MagicString:c016dcd6-cdeb-45df-9fd0-e821bf0e1e62
ping 192.168.254.254
	 
 
After booting the camera, I can see from the tftp server logs that u-boot transfers both "upgrade_info_7db780a713a4.txt" and "success.txt":
	
	
	
		Code:
	
	
		Feb 13 20:41:36 linux in.tftpd[4237]: connect from ::ffff:192.168.1.108 (::ffff:192.168.1.108)
Feb 13 20:41:36 linux tftpd[4238]: tftpd: trying to get file: upgrade_info_7db780a713a4.txt
Feb 13 20:41:36 linux tftpd[4238]: tftpd: serving file from /srv/tftp
Feb 13 20:41:36 linux in.tftpd[4239]: connect from ::ffff:192.168.1.108 (::ffff:192.168.1.108)
Feb 13 20:41:36 linux tftpd[4240]: tftpd: trying to get file: success.txt
Feb 13 20:41:36 linux tftpd[4240]: tftpd: serving file from /srv/tftp
	 
 
Also, the packet capture shows the same TFTP transfers, and the ping to the TFTP server IP address, confirming that the command has been executed by u-boot:
	
	
	
		Code:
	
	
		57   14.951755   192.168.1.108   192.168.254.254   TFTP   111   Read Request, File: upgrade_info_7db780a713a4.txt, Transfer type: octet, timeout=1, tsize=0, blksize=1468
58   14.956915   192.168.254.254   192.168.1.108   TFTP   131   Data Packet, Block: 1 (last)
59   14.959557   192.168.1.108   192.168.254.254   TFTP   60   Acknowledgement, Block: 1
62   15.153631   192.168.1.108   192.168.254.254   ICMP   60   Echo (ping) request  id=0x0000, seq=0/0, ttl=255 (reply in 63)
63   15.153902   192.168.254.254   192.168.1.108   ICMP   42   Echo (ping) reply    id=0x0000, seq=0/0, ttl=63 (request in 62)
91   15.563283   192.168.1.108   192.168.254.254   TFTP   93   Read Request, File: success.txt, Transfer type: octet, timeout=5, tsize=0, blksize=1468
92   15.568086   192.168.254.254   192.168.1.108   TFTP   55   Data Packet, Block: 1 (last)
93   15.570812   192.168.1.108   192.168.254.254   TFTP   60   Acknowledgement, Block: 1
	 
 
It should be possible to flash the firmware using the same u-boot commands described in 
Dahua IPC unbricking / recovery over serial UART and TFTP (I haven't tried since I have no need at this moment).