[comp.sys.amiga.tech] SDB and tracing through the ROMs

mcp@ziebmef.uucp (Marc Plumb) (12/28/88)

I'm trying to reverse-engineer the disk validator, and encoutering a few
snags.  Could someone help me out?

What I'd really like to do is put breakpoints in the ROMs and work through
things that way, but I haven't yet found the magic flag that write-enables
the WCS.  The only likely sounding thing, the "memory overlay bit" on
PA0 of 8250 A, crashes the machine.  Obviously not what I want.

Against the day whan I find out (I could use help there, too), does SDB
mind encountering breakpoints in a foreign process?  I suspect it would
get upset if it hit one while the program it was debugging was stopped, but
if I put my test program into an infinite Wait(), would things work, or
does it mess around with the task structure?  The features to debug
device drivers suggest that something's possible, but the docs don't
go into any detail.

Also, in the interim, my attempts involving patching the rn_RestartSeg
vector to go through a jump to the real code I set up in RAM cause
machine crashes.  Can someone tell me what I'm doing wrong?

Current procedure:
OpenLibrary("dos.library", 0L) and find the root node.
Look at the rn_RestartSeg vector.  It holds 0x3ffc6c, a BPTR to
0xfff1b0, a reasonable place in the ROMS.  Disassembling this
location reveals:

00fff1b0: 0000 0000	ori.b	#0,d0
00fff1b4: 0000 038d	ori.b	#-73,d0
00fff1b8: 2401     	move.l	d1,d2
(more reasonable-looking code)

The first word looks like the NULL pointer to the next segment in the
SegList, the second, I don't know (by the docs I've seen, it should
get executed, but although it's harmless, it sure looks like a count
or something), and the rest is code involving a lot of shifts and (a0,dn)
addressing modes.  BCPL compiler, anyone?  (1.3 kickstart, BTW.)

So I try to patch in my own code.  I declare a static array (char code[20]),
round up to the nearest longword, stuff the current contents of
rn_RestartSeg into the first word, two nops after that (since I'm not sure
where the executable code starts in a segment), and then an absolute jump
to 0xfff1b4 (I've also tried with 0xfff1b8).

I patch rn_RestartSeg to hold a bptr to my fake segment, and, while I can
unpatch it again safely, if I insert a floppy (removal is okay) while this
patch is in place, boom!  Guru time.

For the technically oriented, I patched rn->RestartSeg to hold 0x7f2d,
0x1fcb4 in the APTR world, and at that address is found:

0001fcb4: 003f fc6c		ori.b	$6c,usp
0001fcb8: 4e71			nop
0001fcba: 4e71			nop
0001fcbc: 4ef9 00ff f1b4	fmp	fff1b4

I can't see what's wrong with this.  I haven't tried inserting a breakpoint
yet; I wanted to get this obviously trivial thing working first.

So... suggestions?  My eventual aim is to have my format of floppy auto-
recognised when a floppy is stuck in the drive, which I decided was
best achieved by patching in my rn_RestartSeg disk validator, which
would read the boot block, check the DOS type, and possibly punt to
the old one, but might do what the current disk vallidator does
(whatever that is), but using a different handler.

In furtherance of this, I'm trying to reverse-engineer the disk validator.
Any help at any stage of this descent to detail would be appreciated.

-- 
	-Colin (utai.toronto.edu!ncrcan!ziebmef!mcp for now) 

steveb@cbmvax.UUCP (Steve Beats) (12/30/88)

In article <1988Dec27.223345.29513@ziebmef.uucp> mcp@ziebmef.UUCP (Colin Plumb) writes:
>I'm trying to reverse-engineer the disk validator, and encoutering a few
>snags.  Could someone help me out?
>[stuff deleted]
>Also, in the interim, my attempts involving patching the rn_RestartSeg
>vector to go through a jump to the real code I set up in RAM cause
>machine crashes.  Can someone tell me what I'm doing wrong?
>
Yes, you're playing around in system structures and using private fields
that are not guaranteed to remain the same for all Kickstart releases.
You can consider this a polite slap on the wrist if you like :-)  Really
though, what you are attempting to do is completely unsupported, the only
way to take over a small part of the filing system is to write the big part
too and mount that on the appropriate device.

>So... suggestions?  My eventual aim is to have my format of floppy auto-
>recognised when a floppy is stuck in the drive, which I decided was
>best achieved by patching in my rn_RestartSeg disk validator, which
>would read the boot block, check the DOS type, and possibly punt to
>the old one, but might do what the current disk vallidator does
>(whatever that is), but using a different handler.
>
'fraid you have hit a pretty glaring hole in the current AmigaDOS filing
system environment.  Right now, the filing system is mounted on a device
and remains there for all time.  The mounted filing system decides if it
can grok the inserted disk, if it can't, it just says "not a DOS disk" and
gives up.  There is no facility for "passing-on" a disk to an alternate
filing system.  Unfortunately, this is what you need.

Once again, the solution is to mount your own filing system on the trackdisk
unit and do everything yourself.  To handle the case of the ROM filing system
you could send an inhibit packet to it when your task starts up;  this will
prevent it from snooping the disk before you do.  If a disk is inserted that
you don't recognise, simply send an uninhibit to the ROM filing system and
it will then log and check the disk instead.  Of course, you mustn't touch
the disk once this has been done.  There will also be complications when
the oldfs disk is removed and one of your disks is inserted.  Really, this
kind of trickery just ain't supported.


>In furtherance of this, I'm trying to reverse-engineer the disk validator.
>Any help at any stage of this descent to detail would be appreciated.
>
OK, that bit is easy, the disk-validator/restart code does the following
when a disk is inserted or the volume is uninhibited (by format for example).

1.  Read the boot block, if !DOS0 then "not a DOS disk"

2.  Read the root block and make sure the checksum is OK.
    Check various fields in the root block for consistency.  These include
    the hashtable size and the size of the volume name.  Parent key and
    a couple of others are checked to make sure they are 0.  If any of
    these tests fail then "not a DOS disk"

3.  Check the bitmap-valid flag in the root block.  If it's 0 then the
    validator will be called.  Under the old filing system, this involves
    loading it off *SOME* disk and creating a separate process.  Under FFS
    the validator runs on the same task as the main filing system code but
    as a separate co-routine (or thread or lightweight process, whatever :-)
    The validator code is an integral part of FFS, not loaded separately.

The main task of the validator is to check the files on the disk and report
any corrupted headers or duplicate keys etc.  If no uncorrectable problems
are found, then the bitmap is rebuilt and written to the disk (if there is
room).  If there's no room on the disk (which can be the case with floppies)
then just the memory copy of the bitmap will be used and the disk will get
validated every time it is inserted.

I won't go into the details of how the bitmap is built since this isn't
really pertinent to what you were asking about.  Hope this helps though.

	Steve

page@swan.ulowell.edu (Bob Page) (12/30/88)

mcp@ziebmef.UUCP (Colin Plumb) wrote:
>I'm trying to reverse-engineer the disk validator, and encoutering a few

>What I'd really like to do is put breakpoints in the ROMs and work through

How about using the validator in L: ?

>I haven't yet found the magic flag that write-enables the WCS.

My dim view of Amiga hardware says you won't find such a magic flag.

Here's something Kim posted around September 86.  Might be useful.

..Bob

vvvvvvvvvvvvvvvvvvvvvvvvvv from Steve Schoettler vvvvvvvvvvvvvvvvvvvvvvvvvvvvv


                     Making Kickstart RAM writable.
 
 
   If you've ever wanted to modify kickstart routines, here's the
information you've been waiting for.

   If you use metascope and would like to trace your program as it
calls some kernel routine or set breakpoints in the libraries, the
following information should be very useful.

   How many times have you called OpenWindow() and bombed but didn't
quite know why?

   Even with this modification, when you're not interested in writing
to kickstart, you can switch the capability off and it's
write protected just like a normal Amiga!
 
   Of course, this leaves the ram open to crazy programs, but that
simply means that if a program goes wild and happens to write to
a critical area you have to turn off the machine to reboot kickstart,
rather than just inserting workbench.  To me, the ability to debug
is worth it.  Besides I can easily return to write protection.
 
 
First, a few words about how the kickstart sequence works:
 
   When you turn on your Amiga the bootup ROM reads the Kickstart
disk into the Kickstart RAM at $fc0000.  Then the 68000 does a read
to the location $f80000. (Actually, anything with Address bits 19-23
high and A18 low would do).  This condition is detected by a PAL called
DAUGCAS, which write protects the kickstart ram.
 
  There are three methods you could use to disable the write protect:

(1) Install a switch to force the write protect signal (WPRO*) inactive.
    This is the method I used, and is really simple because
    C-A graciously left two holes in the circuit board for the wires
    to my switch.  It could probably be removed (in case you had to
    take it in for servicing at a later time) without leaving any
    traces.  Well, actually you would have to drill a hole in the
    back panel to mount the switch.
 
(2) Replace the PAL with one that had a different equation for the
    WPRO*.  This has the glamor of not needing any solder.
    The equation could be set up to never write protect the RAM,
    but that's probably not such a good idea.

    A better method would be to make the RAM toggle the WPRO*
    signal with every read to $f80000.  A simple C or
    Basic program could be written to read this location.  Just
    so you know what state it's in (WPRO* or not), you could read
    location $ffffff, write something else to it, and read it back
    again.  If it's the same, it's write protected, otherwise it's
    not so put the old value back.

    (By the way, the location you choose should not be any code
    another task might be executing.  Maybe you could overwrite the
    copyright notice.  To be safe, a forbid() and permit() would
    probably be a good idea.)
 
(3) Remove the instruction that reads location $f80000 in the first
    place.  This is in the Boot Rom, so you'd have to change that.
    I don't like that solution because it's permanent.
 
 
   If you like the PAL method (2), you're on your own for now.  I have
figured out how to make the new PAL, but I can't post the equations
and I can't distribute the chips without violating C-A's copyrights.

   I have gotten a preliminary OK from Commodore to distribute the PALs,
and as soon as I get a written OK, I'll let you know about it.
They should cost less than $10.
 
Following is a description of how to install a WPRO* switch
(method (1), above):
 
********** But first, a disclaimer *******************************
****
**** 1. I can't be responsible for anything you do to your Amiga.
****    I believe I've explained this thoroughly enough so someone
****    with soldering experience and a reasonable mechanical
****    intuition can do it without much difficulty, but you
****    are taking your computer into your own hands.
****
**** 2. Commodore may have or may in the future change the layout
****    of the circuit board or change the PAL's, making these
****    instructions obsolete.  If your board doesn't look like
****    what I'm describing, DON'T DO ANYTHING.
****
**** 3. This will void your warranty.
****
**** 4. I represent no company or organization in any way whatsoever.
****
********************************************************************
 
 
   UNPLUG YOUR AMIGA!!!! It will be very easy to strike a metal
object (soldering iron, solder, resistor, wire, watch, etc) across
two consecutive traces and who knows what might happen.
 
   First, you need to take off the cover of your Amiga and take
off the metal shield that covers the circuit boards (yes, all
19 screws and 2 twist tabs).
 
   So we agree on orientation, the front of the Amiga is towards you,
the power supply is on the left, and the parallel port is on the
upper right side.  I will refer to the rear of the Amiga as the
"top."
 
   There is a main mother board, and an L-shaped "daughter board"
which is upside down, above the main board.  The PAL is located
on the daughter board at location J-6.   It's on one of the
inside corners, next to the letter "J" and it says "DAUGCAS"
alongside it.  This is a 20 pin chip.
 
   There should be a white outline of the chip between the
pins with a notch at one end.  From the notch, count pins
clockwise until you get to pin #13, which is the third one from
the upper right corner of the chip. Pin 13 is the WPRO* signal.
 
   Originally, the WPRO* signal went through a resistor and LED
to +5V.  Since WPRO* is active low, the LED would go on during
bootup while the ram was being written, and then go off at about
the time it told you to insert the Workbench, and remain off
until you turned the machine off.

   Well, it's silly to have an LED inside a closed box, so C-A
decided to save costs and not insert the resistor and LED, but
the circuit board should still be the same.
 
   I don't know on how many boards the LED was inserted, or on
how many boards the LED socket will still be around, so inserting
the wire to the switch may be a slightly different procedure for
some of you.
 
   If you follow the trace from pin 13 of DAUGCAS it will go to
one of the resistor terminals.  Insert the stripped end of a wire
into this hole at the left end of the resistor.  (Just heat the
hole with your soldering iron and push the wire through).
 
   As a precaution, before working on the board, put a piece of paper
under where you'll be soldering so solder splats don't hit the
board below.  I didn't get anything on my paper, but it's good
prevention.
 
   Above the resistor space is a white box marked "1" with 2 solder
holes.  Insert the stripped end of another wire in the left-most
of these two holes inside the box.  You now have the two wires
necessary to run to your switch:  one is connected to WPRO* and
the other to +5V.  With the switch "on" you will pull WPRO* hi
(inactive) and make the ram writable.
 
  A note about mounting of the switch.  I suppose you will want to
mount this in the back panel.  This panel is removable, so it's
easy to put it flat on a table and drill a new hole.

   Before you remove the back panel and drill the hole, however,
put the metal shield back on (screws not necessary) and hold your
switch in the location you wanted.  If it's like most switches, it
probably won't fit next to the metal shield UNLESS it's as far right
as possible (over the keyboard jack).

Now, go drill the hole.
 
  When cutting the wires, leave a few inches of slack so they can fit
through the crack in the metal shield in the upper right corner.
(convenient, huh?)
 
Now put it back together and you have switchably writable kickstart!
 


A note about operation:
=======================
 
   For normal operation, leave the switch "off" when you power
up.  This will look and act exactly like a normal Amiga.
To enable writing the ram, turn the switch "on".

   If, after you have been writing the ram, you decide to
write protect it, the switch alone won't do it - TURNING THE
SWITCH BACK OFF STILL LEAVES THE RAM WRITABLE. You need to
either do a read to location $f80000 or turn the machine off
and on again.

   If you want the facility to turn off WPRO* with a switch, you
can use a 3 pole switch with WPRO* in the middle terminal and
+5V on one side and GND on the other, but there isn't a convenient
hole for GND so you'd have to find one on the board. This would
have an immediate reaction with any direction of the switch.
 
 
 
Technicalities:
===============

   All of the above works, but if you want to know a little more
about how, read on.

   The WPRO* signal is actually both an output and input of the
DAUGCAS PAL.  The logic used to generate it has what we call a
"set" term and a "reset" term.  It acts like a S/R flip-flop.

   The "set" term makes WPRO* active when the processor does a read
cycle from an address whose bits 19-23 are high and bit 18 is low.

   The "reset" term comes from the hardware reset line that is active
when the machine powers on.

   Once WPRO* is set, it won't be reset until power on again, and
once it's reset it won't be set until that read instruction.

   WPRO* is both an output and an input of the PAL.  The output is
generated from the above equation, and the input is used to disable
a write signal from ever getting to the RAM.

   The very astute of you might criticize the forcing high of a low
output.  Well, the only time the output is forced is during the read
cycle (a couple hundred nanoseconds), because after that WPRO* is
tricked into thinking it was reset and the output agrees with what
is being forced so no more contention.  The PAL used, according to
the manufacturer, is able to handle voltage applied to outputs up to
Vcc, which is +5V, so we're within specs.
 
********************************************************************
 
Happy hacking!
 
                                         Steve Schoettler
 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.

sean@ms.uky.edu (Sean Casey) (12/30/88)

In article <5595@cbmvax.UUCP> steveb@cbmvax.UUCP (Steve Beats) writes:
|>So... suggestions?  My eventual aim is to have my format of floppy auto-
|>recognised when a floppy is stuck in the drive, which I decided was

|'fraid you have hit a pretty glaring hole in the current AmigaDOS filing
|system environment.  Right now, the filing system is mounted on a device
|and remains there for all time.  The mounted filing system decides if it
|can grok the inserted disk, if it can't, it just says "not a DOS disk" and
|gives up.  There is no facility for "passing-on" a disk to an alternate
|filing system.  Unfortunately, this is what you need.

I thought that this was exactly what FFS on floppies combined with
autodiskchange does. Have I got it wrong?

Sean
-- 
***  Sean Casey                        sean@ms.uky.edu,  sean@ukma.bitnet
***  Who sometimes never learns.       {backbone site|rutgers|uunet}!ukma!sean
***  U of K, Lexington Kentucky, USA  ..where Christian movies are banned.
***  ``My name is father. You killed my die. Prepare to Inigo Montoya.''

sean@ms.uky.edu (Sean Casey) (12/30/88)

In article <10967@swan.ulowell.edu> page@swan.ulowell.edu (Bob Page) writes:
>mcp@ziebmef.UUCP (Colin Plumb) wrote:
>>I haven't yet found the magic flag that write-enables the WCS.
>
>My dim view of Amiga hardware says you won't find such a magic flag.

Apparently the people who wrote Dragon's Lair did. It's there somewhere.
How about it, CA? How is it done?

Sean
-- 
***  Sean Casey                        sean@ms.uky.edu,  sean@ukma.bitnet
***  Who sometimes never learns.       {backbone site|rutgers|uunet}!ukma!sean
***  U of K, Lexington Kentucky, USA  ..where Christian movies are banned.
***  ``My name is father. You killed my die. Prepare to Inigo Montoya.''

kodiak@amiga.UUCP (Robert R. Burns) (12/31/88)

In article (Colin Plumb) writes:
)00fff1b0: 0000 0000	ori.b	#0,d0
)00fff1b4: 0000 038d	ori.b	#-73,d0
)00fff1b8: 2401     	move.l	d1,d2
)(more reasonable-looking code)
)...
)BCPL compiler, anyone?  (1.3 kickstart, BTW.)
)...
)For the technically oriented, I patched rn->RestartSeg to hold 0x7f2d,
)0x1fcb4 in the APTR world, and at that address is found:
)
)0001fcb4: 003f fc6c		ori.b	$6c,usp
)0001fcb8: 4e71	4e71		nop nop
)0001fcbc: 4ef9 00ff f1b4	fmp	fff1b4

Well, that *fmp* instruction will get you every time! :-)

Seriously:
1.  You're looking at a BCPL segment global table.  The 0000 0000 is indeed
    a NULL next pointer, and the 0000 038d is the size of the segment.
    You have now entered the twilight zone.  The reason you're crashing is
    because BCPL segments are different than any other kind of segment, and
    the lie about either the next segment pointer, or (more likely) the size
    of this one caused the crash.  Moreover, execution does not start at the
    first code in the first segment.  I honestly don't want to go into more
    detail lest folks start using the mechanisms involved, because they are
    structurally flawed and will break if too many people use them.  Hope
    you're not the "knowledge for knowledge's sake" type :-).
2.  This mechanism (if you get it to work) will not be supported for 1.4,
    but I see Steve has already said that.
-- 
Bob Burns, amiga!kodiak                   _
| /_  _|. _ |      Commodore __          |_) _ |_  _ )'
|<(_)(_)|(_\|<      /\ |  ||| _` /\      |_)(_\| )(_\ |
| \ Software    ___/..\|\/|||__|/..\___           Faith

grr@cbmvax.UUCP (George Robbins) (01/01/89)

In article <1988Dec27.223345.29513@ziebmef.uucp> mcp@ziebmef.UUCP (Colin Plumb) writes:
> I'm trying to reverse-engineer the disk validator, and encoutering a few
> snags.  Could someone help me out?
> 
> What I'd really like to do is put breakpoints in the ROMs and work through
> things that way, but I haven't yet found the magic flag that write-enables
> the WCS.  The only likely sounding thing, the "memory overlay bit" on
> PA0 of 8250 A, crashes the machine.  Obviously not what I want.

There is no magic flag.  What you must do to reenable writing to the
control store is issue a 68000 reset instruction, then get things started
up again.  This is, in general, non-trivial task, though I suspose for a
stand-alone game it isn't that hard.

The "memory overlay bit" or "OVR" bit simply controls whether ROM or
"chip" memory is mapped at location 0.  This is neccessary so that the
processor can find it's way to the normal "ROM" area.

It is of course fairly simple to modify the RAM/ROM tower board to
disable the ROM write protect feature...
-- 
George Robbins - now working for,	uucp: {uunet|pyramid|rutgers}!cbmvax!grr
but no way officially representing	arpa: cbmvax!grr@uunet.uu.net
Commodore, Engineering Department	fone: 215-431-9255 (only by moonlite)

scott@applix.UUCP (Scott Evernden) (01/07/89)

>>>I haven't yet found the magic flag that write-enables the WCS.

Based on a note by Martin Brenner, I quickly tried this in Manx C
and it sure seems to work

	main()
	{
		* (long *) 0x80 = 0xFC00D0;	/* a RESET */
	#asm
		trap	#0
	#endasm
	}

Compile and run.  The machine'll reboot, but the WCS will be
unprotected and the BootRom will be visible at 0xF80000.

Please don't anyone use this for amything.

-scott