Welcome, Guest. Please login or register.

Author Topic: KickWork  (Read 23198 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« on: November 28, 2007, 07:49:00 AM »
The easiest solution for this would be to patch the trackdisk.device to spoof normal KS 1.x bootblock instead of the KICK-block. Then you'd just need to mark the area used by the kickstart ROM as "used" in the bitmap.
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #1 on: November 28, 2007, 09:02:48 PM »
I wrote some nice tool to create combined A1000 kick + bootable floppy, imaginatively called "mkkickwork". Once the program has created the .adf you still need to populate the disk with the system files (and you can't fit them all, obviously, I threw out Prefs, narrator/translator/say and FastFileSystem).

Anyway, it works:

(I don't have a A1000 so I had to use UAE for testing)
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #2 on: November 28, 2007, 10:27:10 PM »
http://www.iki.fi/sintonen/temp/mkkickwork.exe (amigaos m68k)

usage is quite simple:
Code: [Select]
.> mkkickwork path:to/kick13.rom kickwork.adf
You obviously need the KS ROM in a file, but that shouldn't be a problem (and it can be extracted from the existing kick floppy if really necessary). The program writes ADF file, which you can then write to a real amiga floppy by using your favorite ADF-write tool.

The generated floppy is bootable (on A1000 only, with default options;-)), but doesn't contain any system files. It does boot but doesn't do anything else than sit in the CLI prompt. You probably want to copy in some extra files there to make it usable.

I'll prolly put the source code for the tool up soonish.

 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #3 on: November 28, 2007, 11:37:38 PM »
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #4 on: November 29, 2007, 09:42:01 AM »
Some words on how it works:

Basically the app writes a patched ROM image to the KICK floppy disk. The patch catches the OS reading the floppy bootblock (first two blocks) and if 'KICK' identifier is located it instead returns a valid bootblock. This allows the OS to idenfity the disk as bootable OFS (DOS\0), rather than df0:KICK.

The application loads the kickstart and then scans it for the locations to patch. If it finds the needed locations it then inserts the abovementioned trackdisk.device patch. Finally the program writes out a OFS disk image (.adf) containing first the KICK block + the KS ROM to allow A1000 bootstrap ROM to load the KS ROM, and then OFS rootblock + bitmap block with the area for the KS ROM pre-allocated.

The trackdisk.device CMD_READ patch itself is some really tight m68k assembly since I didn't want to overwrite any functional code inside the KS ROM. Currently it fits exactly over the copyright notice inside the KS ROM image beginning (type hex some kick1.2 or kick1.3 image to see the text it overwrites). The patch works by hooking the trackdisk.device/CMD_READ command which is used to read blocks off disk (check trackdisk.doc autodoc CMD_READ for details). At boot the KS ROM bootstrap uses CMD_READ to read the floppy beginning to see if it is bootable, so once we make sure that proper bootblock is returned it'll automagically work.

Later the KS ROM also uses CMD_READ to identify the filesystem of a inserted floppy (you get dfx:KICK if you insert KICK floppy using unpatched KS ROM). The patch naturally catches this CMD_READ aswell and again provides the required identification (DOS\0 to indicate OFS filesystem).

The program isn't really that complicated, the real magic went into figuring out how to patch the trackdisk.device CMD_READ. Once that was sorted out the rest was pretty straight-forward.

Finally, I really have no clue how the original KickWork works. It might do something similar, but for verification I'd need to take a look at ADF of such KickWork floppy.
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #5 on: November 29, 2007, 04:53:18 PM »
Ok, I took a look at the original KickWork now. It has series of patches to the Kickstart ROM. The patches are tied to specific KS ROM version (meaning you need separate disks for every ROM).

The patches are:

strap:
- Modify code so that it accepts other than DOS\0 as bootable device (allows booting from KICK disk).
- Modify palette of the "insert floppy" display.
- Modify the "insert floppy" gfx slightly.

Workbench:
- Change workbench titlebar from "Workbench release 1.x." to "AMIGO KickWork  1.x. " (x being the KS rom revision).
- Modify Workbench so that it accepts other than DOS\0 floppies as DOS one (allows KICK disk with proper filesystem to work).

Finally new ROM checksum is poked in.


So in short it takes a different route, but functions pretty similar way. My patch doesn't do all those fancy visual modifications though, it tries to keep the ROM as unmodified as possible.

The floppy itself gets modified during the installation process (bootblock DOS\0 gets replaces with KICK). I'd guess the area where it writes the KS ROM is preallocated in the disk bitmap.

Finally there is one bootblock patch that seemingly does nothing: It replaces author's name "Loew" with "Loew" (no change). I'd guess this is a simple check to make sure the copyright notice hasn't been modified.
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #6 on: November 30, 2007, 07:36:19 AM »
@da9000
Quote
when you say "The application loads the kickstart and then scans it for the locations to patch.", do you scan certain fixed locations (so it only works on certain Kickstart versions), or some other form of heuristic (so the program will work with other Kickstart versions) ?

My software indeed has heuristics to scan for the locations to patch (newtdread and oldtdreadptr pointers).

It has worked with all KS 1.x I've tried so far. It'll probably work with early KS 0.x betas, too.
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #7 on: December 01, 2007, 01:49:50 PM »
@da9000
Code: [Select]

static __inline u_int32_t rl(const u_int8_t *p)
{
    return (u_int32_t) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
}

static __inline int romptr(u_int32_t p)
{
    return p >= ROMSTART && p < ROMEND;
}

for (i = 8; i < 512; i += 2)
{
    static const u_int8_t header[] =
      &quot;\xff\xff\xff\xff\x0d\x0a\x0a&quot; &quot;AMIGA ROM Operating System&quot;;
    u_int8_t * const p = (u_int8_t *) rom + i;

    if (!memcmp(p, header, sizeof(header) - 1))
    {
        newtdread = p;
        if (verbose > 1)
        {
            fprintf(stderr, &quot;0x%06x: Patch position\n&quot;,
              (u_int8_t *) newtdread - (u_int8_t *) rom + ROMSTART);
        }
        break;
    }
}

for (i = 8; i < ROMSIZE - 40; i += 2)
{
    u_int8_t * const p = (u_int8_t *) rom + i;
    u_int32_t p1, p2;
    p1 = rl(p);
    p2 = rl(p + 8);
    if (romptr(p1) && romptr(p2) &&
        rl(p + 4) == p1 && rl(p + 12) == p2 &&
        romptr(rl(p + 16)) && romptr(rl(p + 20)) &&
        rl(p + 24) == p1 && rl(p + 28) == p1 && rl(p + 32) == p1)
    {
        const u_int8_t *func = (u_int8_t *) rom + p2 - ROMSTART;
        if (rl(func) == 0x48E70038 && rl(func + 4) == 0x26690018)
        {
            oldtdreadptr = p + 8;
            if (verbose > 1)
            {
                fprintf(stderr, &quot;0x%06x: trackdisk.device CMD_READ function ptr\n&quot;,
                  (u_int8_t *) oldtdreadptr - (u_int8_t *) rom + ROMSTART);
            }
            break;
        }
    }
}

Efficiency does not matter here. The code is executed once when creating the disk.

The first loop finds the strings at the beginning of the ROM (it's quite pointless since in fact I think the strings are always at the same offset for all pre-2.0 ROMs). This is where the patch code will be placed.

The second loop is more magic, it locates the jumptable entry for the trackdisk.device CMD_READ command. There it looks for certain combination of pointers, and also has some code matching for the beginning of the actual cmd_read routine. The magical pattern is:

Code: [Select]

ptr1 ; CMD_INVALID
ptr1 ; CMD_RESET
ptr2 ; CMD_READ
ptr2 ; CMD_WRITE
ptr3 ; CMD_UPDATE
ptr4 ; CMD_CLEAR
ptr1 ; CMD_STOP
ptr1 ; CMD_START
ptr1 ; CMD_FLUSH

Once the code finds this pattern of pointers it then checks the code pointed by ptr2. It checks for:
Code: [Select]

ptr2:
    movem.l a2-a4,-(sp)
    move.l  (IO_UNIT,a1),a3

Those are the first two instructions of the cmd_read routine (actually read/write.. as you can see both CMD_READ and CMD_WRITE point to the same routine, the routines are so similar it helped to reduce the codesize to combine them).

Once this jumptable entry is located it is changed to point to the first pointer (where we've copied the patch code to). The patch code is adjusted to jsr to the original cmd_read(write) routine.

Obviously this isn't the only way to patch the trackdisk.device, there are several other ways to do it aswell. One would been by patching the trackdisk.device BEGINIO vector for example. However, in my case I had very little storage left for my patch so to simplify the patchcode I had to locate the patch to as close to actual read operation as possible. Patching BEGINIO would have required for the patch routine to perform further checking to make sure it is a CMD_READ operation.
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #8 on: December 03, 2007, 02:50:11 PM »
@da9000
Quote
rl()

It's big endian 32bit integer read, I did it this way so that the source is endian safe (it works with any endianity, say for example x86). The rl() comes from "read long", wl() is short from "write long".

Quote
where do you check for ptr3 and ptr4?

romptr(rl(p + 16)) and the call afterwards are only checking bounds, right?

Bounds checking of ptr3 and ptr4 is enough, I just check that they're pointers to ROM.
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #9 on: December 03, 2007, 03:15:21 PM »
@da9000
Quote
I assume you're want endianess safety because you're a UAE user?

Nah, I wanted the code to be nice. Locking your code to certain endianess is quite stupid.

I wrote the app on my peg2 running MorphOS, but tested it using WinUAE (afaik E-UAE doesn't do A1000 emulation).
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #10 on: December 07, 2007, 09:18:00 AM »
@orange

A1000 only has 256KB WOM.
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #11 on: December 07, 2007, 09:21:18 AM »
@TjLaZer
Quote
Whats the -b switch do exactly?

From the program help page:
Quote
create DOS bootable floppy rather than A1000 kickstart disk


Basically it makes a normal DOS floppy you can use on any amiga. You can then fill it with whatever files you need. Once done, you can make it KICK-floppy by just writing the first 512 bytes with 'KICK' + zeros.
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #12 on: December 07, 2007, 11:00:56 AM »
@orange
Quote
that hasn't stopped rloew doing it

That requires either 512KB WOM hack + modified A1000 bootstrap, or skick kind of hack for the 2nd half of the ROM.

This is out of scope for mkkickwork.
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #13 on: December 14, 2007, 09:22:58 AM »
@TjLaZer

Oi! Nice to hear it works on the real thing, too :-)
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show all replies
    • http://www.iki.fi/sintonen/
Re: KickWork
« Reply #14 on: March 25, 2008, 01:44:00 AM »
There's no fuss. KickBench was just implemented in a silly way: Writing the disk all the time, when in fact there was no need for that.

But hey if KickBench did the work for you, no problem.