My first couple of questions trying to understand this are:
Within the final 20 bytes is the "nonce", which is iterated to find a hash which is less than a given value (the "difficulty"). I'm guessing the timestamp is dictated somehow and I can't arbitrarily change it? Do I need to update the timestamp as I'm iterating?
While you are iterating, trying to find a block header that hashes to something less than the current target, you increment the nonce in the header, and when that overflows, increment the extra-nonce in the coinbase script.
During iteration, the timestamp can increment, and the prior block can change, because someone else has mined a new last block at the end of the most difficult chain. When this happens, you incorporate the new timestamp and/or prior block into your header, and you can then reset the nonces, and start incrementing them again.
This is why the extra-nonce is generally no more than one or two bytes. Because you can keep resetting it when anything else in the header changes, and in any case, at least once a second.