English Amiga Board

English Amiga Board (https://eab.abime.net/index.php)
-   Coders. Asm / Hardware (https://eab.abime.net/forumdisplay.php?f=112)
-   -   Correct way to hard reset in the bootblock on 1.3-3.1? (https://eab.abime.net/showthread.php?t=108218)

Photon 12 September 2021 00:54

Admiral, we are sort of jabbing from different perspective to reach a goal, bootblock code that works on all OS versions that can kill resident viruses (as a shorthand). It started as weird behavior (so that's what I reported in OP), now it turns out my code was mostly correct and we have some code that partially helps with killing viruses on 2.0+. I understand that you're confused, because the entire thread must be read as context. A 'spurt session' to try to solve the problem, with some great info. :great

Perhaps someday there will be universal code for this utility work, but for now I just need to optimize 36 bytes. Send 36 bytes pls. :D

admiral 12 September 2021 02:51

Quote:

Originally Posted by Photon (Post 1506177)
but for now I just need to optimize 36 bytes. Send 36 bytes pls. :D

w/o your bootblock's full sources, I can only suggest crunching your bootblock :cheese

Photon 12 September 2021 14:31

I've just replaced a legacy piece of code with shorter code, so I have bytes to spare! I'm now in the process of testing on all systems and cleaning up the source. Then it will be shared with source here :great

hooverphonique 12 September 2021 14:50

Wouldn't rebuilding execbase effectively destroy any virus' connection to the system, regardless of if its code is still in memory or not? I would think so.

Photon 12 September 2021 15:06

Quote:

Originally Posted by hooverphonique (Post 1506249)
Wouldn't rebuilding execbase effectively destroy any virus' connection to the system, regardless of if its code is still in memory or not? I would think so.

Coldreboot() doesn't clear vectors or RAM, so Ross's second code is used.

Clearing RAM is useful only for tests outside your dev env where all code works. If junk in bitplanes, hardreset to clear RAM and if it works you found the bug (relying on some memory being cleared) in five seconds. This can only be done on 1.3, unless I manually clear it first on 2.0+.

(Side note: And Ctrl-Amiga-Amiga or code softreset clears all RAM on one specific setup, ECS machine with KS1.3... it's a mess. It would be very nice if somehow this could be fixed, but...)

admiral 12 September 2021 20:57

Quote:

Originally Posted by hooverphonique (Post 1506249)
Wouldn't rebuilding execbase effectively destroy any virus' connection to the system, regardless of if its code is still in memory or not? I would think so.

ColdCapture() runs before execbase checksum is even checked, so you'd have to explicitly wipe that one.

Photon 14 September 2021 18:03

The bootblock is now feature complete and I'm prettifying it without going over 1K.

My question in OP was based on emulation behavior, so it is answered by this:

Quote:

Originally Posted by Toni Wilen (Post 1506037)
Sounds like you trigger KS 1.3 bug, there is always 1/227 chance of NTSC misdetection.

I sent it to Toni and he replied emulation is always started with fixed data - regarding this KS1.3 bug, in a real Amiga there's always some randomness. WinUAE, too, can get this randomness. It's enough to boot without the disk and insert it after the disk picture is show to introduce some, and then the bug triggers, not every time, but likely 1/227 times.


I also wanted to ask about these two comments seen together:

Quote:

Originally Posted by Toni Wilen (Post 1506037)
68020+ prefetch long words. If unaligned, it still prefetches full long from aligned address (=address - 2).

Quote:

Originally Posted by a/b (Post 1506034)
Wasn't that debunked?

Is it settled by Toni's comment? I.e. reset;jmp (a0) combo must be aligned by CNOP 0,4 to not fail on 68020+?

Toni Wilen 14 September 2021 18:17

Quote:

Originally Posted by Photon (Post 1506579)
sent it to Toni and he replied emulation is always started with fixed data - regarding this KS1.3 bug, in a real Amiga there's always some randomness. WinUAE, too, can get this randomness. It's enough to boot without the disk and insert it after the disk picture is show to introduce some, and then the bug triggers, not every time, but likely 1/227 times.

It can happen but don't depend it. Any version update can change it. Almost anything can change it :)

Quote:

Is it settled by Toni's comment? I.e. reset;jmp (a0) combo must be aligned by CNOP 0,4 to not fail on 68020+?
I didn't say it would fail. 68020 will always prefetch at least 1 word (if unaligned), jmp (a0) fits in single word: it will work even if unaligned. (at least as long as jmp(a0) is not located at the very end of memory space, where next address is some read sensitive IO..)

Photon 14 September 2021 18:40

Quote:

Originally Posted by Toni Wilen (Post 1506581)
It can happen but don't depend it. Any version update can change it. Almost anything can change it :)

As I see it, current emulation behavior will cause every Quickstart A500 configuration saved with a bootable floppy image in DF0:, to always boot in NTSC mode. I just detect it, I can change nothing :)

Anyway, the cause is known now, so for me it's answered. But it was good that I asked because my boot block is in better shape.

Quote:

Originally Posted by Toni Wilen (Post 1506581)
I didn't say it would fail. 68020 will always prefetch at least 1 word (if unaligned), jmp (a0) fits in single word: it will work even if unaligned. (at least as long as jmp(a0) is not located at the very end of memory space, where next address is some read sensitive IO..)

AFAIK it's the reset instruction that has to be aligned, so that the jmp instruction is prefetched with it? And then the jmp instruction is always unaligned, so even if that's OK, that's not the test case where it could fail?

I.e. The case to be debunked is when the reset instruction is unaligned?

Quote:

Originally Posted by admiral (Post 1506297)
ColdCapture() runs before execbase checksum is even checked, so you'd have to explicitly wipe that one.

I would like there to be no chance for a virus to thwart my Execbase-destroying efforts. :) Do I need to explicitly wipe it before destroying Execbase and resetting, then?

If so, what is the correct way to wipe ColdCapture() before reset?

ross 14 September 2021 18:45

Quote:

Originally Posted by Photon (Post 1506586)
If so, what is the correct way to wipe ColdCapture() before reset?

clr.l $2a(a6)


EDIT: but if execbase is destroyed there is no need to clear it..
I explicitly used
st 7.w
because in any ROM there is a check for an odd execbase address (which of course cannot be accepted),
therefore nothing can be executed from resident vectors or pass the checksum checks.

Toni Wilen 14 September 2021 19:14

Quote:

Originally Posted by Photon (Post 1506586)
AFAIK it's the reset instruction that has to be aligned, so that the jmp instruction is prefetched with it? And then the jmp instruction is always unaligned, so even if that's OK, that's not the test case where it could fail?

I.e. The case to be debunked is when the reset instruction is unaligned?

I just tested. It works.

Unaligned RESET followed by JMP (A0) in next long word. Cache disable and flush followed by dozens of NOPs before RESET/JMP (A0) to guarantee flushed pipeline. (JMP instruction executing confirmed by testing with odd A0. It crashed.)

Photon 14 September 2021 19:39

Quote:

Originally Posted by Toni Wilen (Post 1506593)
I just tested. It works.

Unaligned RESET followed by JMP (A0) in next long word. Cache disable and flush followed by dozens of NOPs before RESET/JMP (A0) to guarantee flushed pipeline. (JMP instruction executing confirmed by testing with odd A0. It crashed.)

Sh*t. I just re-checked the HRM example and the RESET instruction is actually unaligned. (Because it's preceded by a lea.l 2,a0.) Sorry. I just don't exactly how prefetch works in exact detail.

This has to be the most confusing section in the entire book, not least because of calling a normal soft reset a "Cold Reboot". :nuts

The 'why' question remains interesting. It seems to be the jmp (a0) instruction that should be aligned. Could it fail to prefetch jmp (a0) under some circumstances? That section only mentions as reason that the RAM will disappear when the reset instruction is executed. Could DMA interfere? The example doesn't turn off DMA. Could it be required from an early A1000 hardware bug?

I'll change my code to follow HRM of course, so maybe it's best pursued in a dedicated thread. Annoying as hell :rolleyes

Quote:

Originally Posted by ross (Post 1506588)
clr.l $2a(a6)


EDIT: but if execbase is destroyed there is no need to clear it..
I explicitly used
st 7.w
because in any ROM there is a check for an odd execbase address (which of course cannot be accepted),
so not even by chance you'll being able to execute something or pass checksum checks.

I'm not sure what a/b meant, maybe something like
1. Your code destroys (actually not, asks ROM to later destroy) Exec and resets
2. Reset invokes ColdCapture()
3. ROM notices Exec is bad and rebuilds it, clearing ColdCapture()

...and that because of 2, if ColdCapture() has virus code it could be prepared and nonetheless "re-inject itself"/restore Exec values it saved when first injecting itself? Then Exec wouldn't be rebuilt.

ross 14 September 2021 19:49

Quote:

Originally Posted by Photon (Post 1506599)
I'm not sure what a/b meant, maybe something like
1. Your code destroys (actually not, asks ROM to later destroy) Exec and resets
2. Reset invokes ColdCapture()
3. ROM notices Exec is bad and rebuilds it, clearing ColdCapture()

...and that because of 2, if ColdCapture() has virus code it could be prepared and nonetheless "re-inject itself"/restore Exec values it saved when first injecting itself? Then Exec wouldn't be rebuilt.

I highly doubt that reset code executes from resident vectors without checking checksums first, so if you have IRQs disabled and cleared the vector or checksum and you do a reset, for any virus it is impossible to reinject itself.
But someone could have patched _LVOColdReboot()..
Well, destroying execbase sure do the job :)

Photon 14 September 2021 20:23

Ahem. Sorry again. :o The HRM section about resetting actually doesn't say anything about jmp (a0) having to be aligned. It aligns the Supervisor() target address. Must all code invoked by supervisor state be 4-aligned? SuperState() on 2.0+ doesn't.

Also if things can be patched and monitored maybe it's best to do as much as possible with hardware code. TRAP into supervisor instead of using Exec etc. If we're turning off ints anyway, I mean...

a/b 14 September 2021 21:06

Can you link the reset code you are looking at? I just checked elowar http://amigadev.elowar.com/read/ADCD.../node02E3.html, PDF and the actual book, and they have the same code: reset is longword aligned and shares the same longword with jmp (a0) (which is the idea).
What I'm concerned about is jumping to a RAM address (too soon) after reset. Reset takes 132 cycles so there is plenty to time to fetch the next opcode, but at what point within those cycles is RAM replaced by ROM? Immediatelly, after the next opcode fetch, ...? If you jump into RAM (e.g. lea 2.w,a0 + jmp (a0)) does that work with all hardware profiles? So I consider jumping into ROM ($0fxxxxxx) safer.

About the reboot vectors. Yeah, manual exec nuke from the orbit (e.g. nuke exec base or one of checksumed vectors so the checksum doesn't match) is the only way to be sure. Or fix them and redo the checksum (well, as long as you assume the virus didn't take over your MMU). For example:
Code:

        clr.l        ColdCapture(a6)
        clr.l        CoolCapture(a6)
        clr.l        WarmCapture(a6)
        lea        SoftVer(a6),a0
        moveq        #(ChkSum-SoftVer)/2-1,d0
        moveq        #-1,d1
csum        sub.w        (a0)+,d1
        dbf        d0,csum
        move.w        d1,(a0)


Photon 15 September 2021 13:22

1 Attachment(s)
Shoulda checked my black HRM I guess. It just sounded like this code was final. In this example (see attachment), the reset instruction is unaligned.

I'm assuming the hardware makes sure the "zeropage" has something in it (even from a poweron) so that the CPU can function. Like providing a jump into ROM at the a0 target address.

There's no hope of fitting anything together with some elaborate antivirus on a bootblock. It's mostly for stopping relatively simple early viruses when testing old, unknown disks. If it prevents a resident virus from staying in memory, that's a good enough hard reset.

a/b 15 September 2021 13:45

Ah, ok... It must be one of the earlier editions (mine is 3rd edition from 1991). Just checked my PDF collection, it's probably the revised&updated edition from 1989 (I was still in the c64 waters at the time).
One way to explain it is that they probably used an optimizing assembler that changed 2 to 2.W, in which case everything fits together nicely. A few lines underneath is move.l 4,a6, and you typically don't write that in your size constrainted ROM code (it's move.l 4.W,a6), which supports this explanation.

admiral 15 September 2021 14:41

Quote:

Originally Posted by a/b (Post 1506613)
About the reboot vectors. Yeah, manual exec nuke from the orbit (e.g. nuke exec base or one of checksumed vectors so the checksum doesn't match) is the only way to be sure. Or fix them and redo the checksum (well, as long as you assume the virus didn't take over your MMU).

Note that while ColdCapture is checksummed, it runs before the checksum check does, so it needs to be nuked explicitly. Furthermore, if set to non-zero (to nuke checksum), it will be called, which is not the intended effect.

So you'd need to clear ColdCapture _and_ nuke one of the other two with a non-zero value.

Furthermore, clearing the vectors and recalculating checksum is not good enough, as the kept ExecBase could have a hook elsewhere.

Photon 15 September 2021 15:15

a/b, it's more likely that a mistake was left in the code, and that this was corrected. (And despite the unaligned RESET, it might not have been a mistake at the time. One of my absolute thoughts is: "You can never be future-compatible, you can only be backwards compatible or not".) And when KS2+ released, a function to do it was added, even though the old code from 1989 works fine on KS2+ (for a soft reset).

For a hard reset, you could say that I need to reset without using the OS, since the OS could be compromised. (Disable, Supervisor/SuperState, ColdReboot could all be "hacked".)

But I don't want some overthought, overwrought antivirus code that may fail on some system.

I could take over the hardware, nuke Exec, hardware reset and prevent most of it and that's fine. For the soft reset I'll use the only allowed code, 2nd edition. :)

If I am to do this, I need a non-Supervisor() way to read VBR.

Photon 15 September 2021 23:08

This wall of code replaces the code in OP. It's tested in WinUAE on A1200-060 3.1, stock A1200 3.1, A500 3.1 and A500 1.3, and on real A500-ACAPlus-3.1 and A500 1.3.

The code can be run from assembler/CLI/WB as is, but ADF is also attached. If something is resident (such as invoked Early Boot menu, accelerator stuff, or virus), it will report a red color else green, and then wait for LMB=Soft Reset or RMB=Hard Reset. If RMB, it must report green on next bootblock run, or report green on next run from assembler/CLI/WB as long as nothing installs itself resident in s-seq before.

I'm looking for feedback on reliability before I commit. (Edit: Please see the ;** and must be comments.) Cheers. :great

Code:

LowMemChkSum=$24
ChkBase=$26
ColdCapture=$2a
CoolCapture=$2e
WarmCapture=$32
EAllocMem=-198

INTENA        =$dff09a
DMACON        =$dff096
COLOR00        =$dff180

ABSEXECBASE        =4                        ;Pointer to the Exec library base
MAGIC_ROMEND        =$01000000                ;End of Kickstart ROM
MAGIC_SIZEOFFS        =-$14                        ;Offs from endROM to KS size
V36_EXEC        =36                        ;Exec with the ColdReboot() function
TEMP_ColdReboot        =-726
LIB_VERSION        =20                        ;offset in Exec
_LVOSupervisor        =-$1e

        JUMPPTR BootCode                ;for assemblers with this function

BOOT:        dc.b "DOS",0
        dc.l 0,880

BootCode:
        move.l 4.w,a6
        move.l #BootCodeE-BootStart,d7

    *--- alloc ---*

        move.l d7,d0                        ;size
        moveq #2,d1                        ;chip
        jsr -198(a6)                        ;AllocMem()
        move.l d0,a1

    *--- copy ---*

        move.l a1,a2
        lea BootStart(PC),a0
.copyl:        move.b (a0)+,(a1)+
        subq.l #1,d7
        bne.s .copyl
        jmp (a2)                        ;jump into chipmem

********************  BOOT START  ********************

BootStart:                                ;a6=Execbase
        move.w #$272,d1
        move.l $2a(a6),d0                ;CHECK COLD- & COOLCAPTURE & KICKTAGPTR
        or.l $2e(a6),d0
        or.l $22a(a6),d0
        beq.s .novirus
        move.w #$822,d1
.novirus:
        move.w d1,COLOR00                ;signify presence

        btst #6,$bfe001                        ;no symbols for these, geddoudaheere...
        beq.s SoftReset                        ;LMB:Soft Reset
        btst #2,$dff016                        ;RMB:Hard Reset
        bne.s BootStart                        ;*magic hand gesture* there is no boot

HardReset:

    *--- disable ints and dma ---*

        move.w #$4000,INTENA                ;disable ints to avoid interference
        move.w #$0580,DMACON                ;and some DMA to avoid delayed prefetch
        clr.w COLOR00                        ;cosmetic (avoid random bg color)

    *--- clr coldcapture, set other two+nuke chkbase(+lowmemchksum?) ---*

        clr.l ColdCapture(a6)                ;must be 0
        st CoolCapture+3(a6)                ;must not be 0
        st WarmCapture+3(a6)                ;must not be 0
        not.l ChkBase(a6)                ;must be not correct (clr is unsafe)

    *--- normal reset but rebuild Exec ---*

        lea.l GoHard(pc),a5                ;<KS20 supervisor address
        bra.s _ElbowTemperatureReboot        ;** really allow Exec to do it?

SoftReset:
        lea.l GoAway(pc),a5                ;<KS20 supervisor address

_ElbowTemperatureReboot:                        ;a5=GoAway or GoHard
;        move.l ABSEXECBASE,a6                        ;HRM code minus load of a5,a6

        cmp.w #V36_EXEC,LIB_VERSION(a6)
        blt.s .pre20
        jmp TEMP_ColdReboot(a6)                        ;Let Exec do it...
        ;NOTE: Control flow never returns to here

;---- manually reset the Amiga ---------------------------------------------
.pre20:        jsr _LVOSupervisor(a6)                        ;supervise-jump to code at (a5)
        ;NOTE: Control flow never returns to here

;-------------- MagicResetCode ---------DO NOT CHANGE-----------------------
        CNOP 0,4                                ;IMPORTANT! Longword align!
GoAway:        lea.l MAGIC_ROMEND,a0                        ;(end of ROM)
        sub.l MAGIC_SIZEOFFS(a0),a0                ;(end of ROM)-(ROM size)=PC
        move.l 4(a0),a0                                ;Get Initial Program Counter
        subq.l #2,a0                                ;now points to second RESET
        reset                                        ;first RESET instruction
        jmp (a0)                                ;CPU Prefetch executes this
        ;NOTE: the RESET and JMP instructions must share a longword!
;---------------------------------------DO NOT CHANGE-----------------------

;-------------- MagicResetCode ---------DO NOT CHANGE-----------------------
;sorry, this is a changed copy. 4 bytes inserted, OK. see *
        CNOP 0,4                                ;IMPORTANT! Longword align!
GoHard:        lea.l MAGIC_ROMEND,a0                        ;(end of ROM)
        sub.l MAGIC_SIZEOFFS(a0),a0                ;(end of ROM)-(ROM size)=PC
        move.l 4(a0),a0                                ;Get Initial Program Counter
        subq.l #2,a0                                ;now points to second RESET
        st 7.w                                        *Exec made odd to force rebuild
        reset                                        ;first RESET instruction
        jmp (a0)                                ;CPU Prefetch executes this
        ;NOTE: the RESET and JMP instructions must share a longword!
;---------------------------------------DO NOT CHANGE-----------------------
BootCodeE:

********************  BOOT END  ********************

        ds.b 1024,0                        ;filler



All times are GMT +2. The time now is 17:08.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.

Page generated in 0.05920 seconds with 11 queries