Uzebox Bootloader V5
Re: New bootloader
Would it be possible to finally have the Power button do something by using interrupts? Something like what Uze tried to do here? He said that it didn't always work, but I thought it might be worth a try.
viewtopic.php?f=4&t=2070#p12855
viewtopic.php?f=4&t=2070#p12855
-
- Posts: 1445
- Joined: Mon Feb 11, 2013 8:08 am
- Location: Brisbane, Australia
Re: New bootloader
I forgot to say
Jubatian - fabulous work. I have no idea how you have time to get so much done.
Jubatian - fabulous work. I have no idea how you have time to get so much done.
Re: New bootloader
I considered exposing programming while developing, but in the end I rather avoided it. Why?nicksen782 wrote: ↑Tue Oct 10, 2017 9:17 pmNow, figure out a way for people to update their bootloaders without using an ISP and you are golden!
(...)
EDIT: And one more question, what about SD writing?
Well, this is a game system, and people here and everywhere are doing lots of hacking around with it, sometimes endig up with codes which might not exactly work as they should, or only work proper, say, 99% of the time. If the remaining 1% is just the game hanging, the Uzebox rebooting, maybe the EEPROM getting wiped, that's not very annoying. Having the Uzebox bricked however is. Especially if you don't have an ISP.
Exposing the interface for games with a built-in check so it can only overwrite the low 60K could be possible (but needs room), but I am rather reluctant to do that too, 10K cycles isn't that much if some broken code is wasting them away. I think better invent methods to use the SPI RAM efficiently than going down that path.
Rewriting the bootloader is tricky. The big problem is that you can only do SPM from the boot section (which is a limitation with good reason even if it works against us in this gaming oriented system). So you have to use code within the bootloader to rewrite the bootloader. Guess you see where this is going... To get this accomplished, the location of the page write routine would have to be fixed, so the update method could rely on it being somewhere to start replacing pages within the bootloader. Along those, it has to write its own write routine somewhere else. Then it has to overwrite the bootloader's original write routine. And finally wipe its own, replacing with the bootloader code which is supposed to go there.
Maybe I will arrange things for that, but I don't think the bootloader will need updates very often. The SD specification I think is very much frozen solid by the millions of consumer crap using the cards, however they could. You can't invent stuff since something somewhere will break and people will get angry. So if this loader works, I expect it could stay around for a quite long while.
My first idea with the button labeled Power was to rather use it to interface the bootloader if you don't have a controller, but that pretty much became unnecessary with the capability of auto-booting an SD with a single .UZE.
Now seeing that there are designs which expose this button, but not Reset (FUzeBox) and others which expose Reset (EUzeBox), I would rather just toss Soft-Reset on it (the same routine which happens on SELECT + START + B + Y in most games).
Besides I already ate up the interrupt vector table since I guessed that the bootloader won't ever need anything else than Timer1 for Video anyway.
Anyway, I will do some hunting after why it could be that SD access works with Harty's loader on your breadboard while my code can not even get to see that there is a card in. That's a bit more important, I guess
Re: New bootloader
I made an update which most notably resolves issues around user-end page programming and reflashing the bootloader. I crammed in an exposed interface which allows user software to load sectors in the user region. So this doesn't allow reprogramming the bootloader. However I also fixed the page program routine's location at the end of the flash, and set the tileset before that. So normally even upgrading the bootloader might not need to touch this part (I imagine changing the tileset wouldn't be the most important thing on someone's mind when he imagined a better bootloader, so if the programming routine is fine, then the issue of reflashing this can be avoided).
The bootloader itself doesn't contain it, but exposes sufficient routines so a write can be added on the user end, even easily piggybacking onto the FAT library (It actually just provides a positioning interface between sectors, it doesn't care what you are doing with the sector. So if you have a pre-uploaded fixed size file which you would want to write, it will be fine, even if it is fragmented).
Re: New bootloader
The bootjack code that CunningFellow linked to will allow a .uze file to reprogram the bootloader, regardless of where the SPM instruction is inside the bootloader (it doesn't need to be at a fixed address, because it searches for it at runtime). The idea is to make it so you can just drag and drop an updated bootloader onto an SD card, and run the .uze file containing the bootjack code, and it'll upgrade the bootloader.
Re: New bootloader
The point was not eliminating the possibility of reprogramming the bootloader, rather that the API exposed to user programs shouldn't allow bricking the Uzebox.Artcfox wrote: ↑Wed Oct 11, 2017 8:09 pmThe bootjack code that CunningFellow linked to will allow a .uze file to reprogram the bootloader, regardless of where the SPM instruction is inside the bootloader (it doesn't need to be at a fixed address, because it searches for it at runtime). The idea is to make it so you can just drag and drop an updated bootloader onto an SD card, and run the .uze file containing the bootjack code, and it'll upgrade the bootloader.
Finding an SPM instruction is one thing. You can of course then build around it with precisely timed interrupts, but what I meant with this loader is that you don't need to do that. I fixed the small ROM sector update routine's address to the very last page, so as long as it doesn't need to be changed, you know the entry point, and can use it to rewrite the rest of the bootloader if you really wanted to.
Re: New bootloader
Cool, I didn't understand what you meant by that before.Jubatian wrote: ↑Wed Oct 11, 2017 8:21 pm The point was not eliminating the possibility of reprogramming the bootloader, rather that the API exposed to user programs shouldn't allow bricking the Uzebox.
Finding an SPM instruction is one thing. You can of course then build around it with precisely timed interrupts, but what I meant with this loader is that you don't need to do that. I fixed the small ROM sector update routine's address to the very last page, so as long as it doesn't need to be changed, you know the entry point, and can use it to rewrite the rest of the bootloader if you really wanted to.
Though my point still stands that for everyone who is still using the old bootloader (which at this point is anyone who has ever purchased or built a Uzebox minus a few people that have checked the forums recently) having a .uze file that uses bootjack should allow them to easily upgrade to the new bootloader, regardless of which version of the old bootloader they are currently using.
-
- Posts: 1445
- Joined: Mon Feb 11, 2013 8:08 am
- Location: Brisbane, Australia
Re: New bootloader
Do a CRC check first on old bootloader to make sure you are not going to try upgrade a custom one.
Putting a standard new bootloader with SNES control routines on hardware than has Atari joysticks would be a "Bad Thing"
Putting a standard new bootloader with SNES control routines on hardware than has Atari joysticks would be a "Bad Thing"
Re: New bootloader
There are other things which I didn't consider for user programming.
The ATMega644 flash is divided in two sections, the RWW and the NRWW sections (Read While Write and No Read While Write). These are 0x0000 - 0xDFFF and 0xE000 - 0xFFFF. The NRWW section is rather straightforward: if you write it, the CPU is halted for the operation, no problem. The RWW however is more tricky. When writing into the RWW, code in the NRWW can still run, but attempting to do anything in the RWW will lead to undefined results (likely the opcode would fetch from a disconnected bus or something alike). Most likely a crash. In the bootloader this allows for displaying a nice uninterrupted progress bar (at least until reaching 0xE000 when the long halts of the NRWW will start to kick around the video signal).
However if you try to call it from an user program, things will not work so well. First of all, writing the RWW section requires some housekeeping work which you must do from NRWW, of course this is granted if you are using the bootloader's routines. However you also have your interrupts in RWW (0x0000), which would make things crash and burn. A "cli" wouldn't work since the bootloader's routines need to "cli" + "sei" on their own (could be fixed, but it will make them larger). Anyway, the end result no matter what you are doing is that you can't have display while writing from the user region. Or the bootloader would have to support even running its own kernel to generate display for you, which would be a hefty piece of API (wouldn't fit).
So even if it worked, it would be ugly.
What might be doable though is an API to ask the bootloader to load something for you, I mean essentially you would transfer control back to the bootloader (like a soft-reset without involving the watchdog), then it would do the loading (displaying its loading bar with its own kernel), and reboot your game. Simplest is asking for another game, but by laying out your resources well, it could be possible to ask it for replacing a section of your game.
The ATMega644 flash is divided in two sections, the RWW and the NRWW sections (Read While Write and No Read While Write). These are 0x0000 - 0xDFFF and 0xE000 - 0xFFFF. The NRWW section is rather straightforward: if you write it, the CPU is halted for the operation, no problem. The RWW however is more tricky. When writing into the RWW, code in the NRWW can still run, but attempting to do anything in the RWW will lead to undefined results (likely the opcode would fetch from a disconnected bus or something alike). Most likely a crash. In the bootloader this allows for displaying a nice uninterrupted progress bar (at least until reaching 0xE000 when the long halts of the NRWW will start to kick around the video signal).
However if you try to call it from an user program, things will not work so well. First of all, writing the RWW section requires some housekeeping work which you must do from NRWW, of course this is granted if you are using the bootloader's routines. However you also have your interrupts in RWW (0x0000), which would make things crash and burn. A "cli" wouldn't work since the bootloader's routines need to "cli" + "sei" on their own (could be fixed, but it will make them larger). Anyway, the end result no matter what you are doing is that you can't have display while writing from the user region. Or the bootloader would have to support even running its own kernel to generate display for you, which would be a hefty piece of API (wouldn't fit).
So even if it worked, it would be ugly.
What might be doable though is an API to ask the bootloader to load something for you, I mean essentially you would transfer control back to the bootloader (like a soft-reset without involving the watchdog), then it would do the loading (displaying its loading bar with its own kernel), and reboot your game. Simplest is asking for another game, but by laying out your resources well, it could be possible to ask it for replacing a section of your game.
Re: New bootloader
I made a new verson (5.0.04) again.
In this I mostly worked on the above mentioned problem, creating an interface which can be called from games. It now would work the following way:
Otherwise I finally fixed the minor flicker issue on the "Insert SD Card" screen, I just forgot that WaitVsync() won't wait if a frame was already passed (you need to wait 2 frames after a long process if you definitely want to arrive to the beginning of a VBlank).
In this I mostly worked on the above mentioned problem, creating an interface which can be called from games. It now would work the following way:
- Your game would use the filesystem library which can use the bootloader's API.
- With the filesystem library, you locate a .uze file, or the image of a .uze file within a larger file.
- You call the bootloader's API function, passing the filesystem structure.
- The bootloader takes over, loads the .uze image (with progress bar as normal), and boots it.
Otherwise I finally fixed the minor flicker issue on the "Insert SD Card" screen, I just forgot that WaitVsync() won't wait if a frame was already passed (you need to wait 2 frames after a long process if you definitely want to arrive to the beginning of a VBlank).