From: Drew Eckhardt (drew@hamlet.cs.colorado.edu)
Date: 05/02/92


From: drew@hamlet.cs.colorado.edu (Drew Eckhardt)
Subject: Re: Non-destructive repartitioning?
Date: 2 May 1992 19:45:54 GMT

In article <1992May2.020223.24197@cs.brown.edu> wcn@cs.brown.edu (Wen-Chun Ni) writes:
>In article <1992Apr30.172545.27745@cs.umu.se> dvldbg@pippin.cs.umu.se (Daniel Brahneborg) writes:
>>I heard something a while ago about some program that could
>>repartition your hard disk without deleting everything on it,
>>but just writing a new smaller FAT. Of course the files had to
>>be on the lower part of the disk. As I have ~160 megs on my HD,

>I want it too, please. I've tried partit and edpart, but they all
>have their limitations.
>
>

It's not a program, but a manual procedure requiring
a. a partitioning program
b. a sector editor

Here it is :

Reformatting your hard disk, and reinstalling all your DOS programs from
scratch can be a real nuissance, and is unecessary.

Breathe a sigh of relief : it is possible to non-destructively repartition
        hard disks.

Notes : Before continuing, make sure you have a RECENT BACKUP.

        I assume that you understand hex arithmatic, and are not
        afraid of a little assembler or DEBUG.

        Actually, a decent partition and disk editor will get you around
        this - NU works gret.

        Of course, the modern programmer doesn't use anything but a
        source level debugger - so I've included some helpful hints
        and the command syntaxes. However, there is no room for
        handholding here : if you screw up, you might have to use
        that backup. Don't do it unless you are confident in your
        abilities.

        Also, this procedure only works with NON-EXTENDED DOS partitions,
        < 64K logical sectors, (DOS 4 large partitions add additional BPB
        fields that I am unsure of - roughly the same procedure applies there
        though. According to Townsend' Advanced MS DOS : Expert Techniques
        for programmers

        offset 26h will have the signature byte 29h if this is
        the case, 20h a dword containing the number of sectors if
        volume size > 64K sectors

        I still use MS-Loss 3.3, with an ~82M partition under disk mangler
        and fall into the tested category)

        Large partitions, handled by a third party partition manager
        and handled so that there are < 64K logical sectors
        work - this was the case with my SCSI disk.

        I will lay down what general procedures you need to know (
        required to read / write the raw disk), as well as the
        data structures we are dealing with. Then I will proceed
        with the entire procedure, which applies the general procedures
        in reading and modifying the data structures. If it looks like
        a tech manual - it is. If you don't grok non-destructive
        repartitioning, you shouldn't be doing it.

        DEBUG has a Hexaritmatic command, h which will add and
        subtract the two operands. You may find this useful.

        IE : I have loaded sector 0 into memory at 0200, and wish to know
        the address of the partition table at 1be.

        -h 200 1be
        03BE 0042

        Where 03BE is the sum, and 042 the difference.

        DEBUG prints a segment before the offset : note that your segments
        will probably not match. The offset is what's important.

        The 80x86 family is LITTLE ENDIAN. This means least significant
        byte first - ie the internal representation of 0x12345678 would be
        78 56 34 12. When dealing with multi-byte quantities, keep this
        in mind.

        When I say word, I mean word as in the Intel documentation :
        16 bits. dword is 32 bits.

        DISK BIOS addresses cylinder, head as zero based, sector
        as 1 based. Same thing for the partition table.

        DOS addresses sectors as 0 based, from the start of the
        logical partition, and as logical sectors which may
        consist of multiple physical sectors.

        Unless otherwise noted, all numbers are hex.

        You're better off using Norton Utilities - but Debug works fine
        too.

        This document is sort of a quick hack 8^)

Tools :

Required : DEBUG, and a disk defragmenter

Optional : partition editors (NOTE!!!! Make sure these DO NOT perform
           any formatting, and allow you to edit partitions in the
           REAL order they appear on the disk.), the Linux FDISK program,
           utilities that save an image of the boot sector FATs, and
           directory (IE Norton's Format Recover), a raw disk editor
           (Norton Utilities NU)..

Procedures :
Editing memory with debug :

d ADDRESS l LENGTH

will dump memory

f ADDRESS l LENGTH values

will fill memory.

Reading and writing DOS logical sectors (using debug):

Reading is accomplished using the debug l command.

l ADDRESS DRIVE SECTOR COUNT

Where ADDRESS is the hex address of where to put the data,

DRIVE is a 0 based drive number (IE A:=0, B:=1, C:=2, etc. If there
is only one floppy drive, it is considered both A: and B: as it is
in DOS)

SECTOR is a zero based sector number. Of interest to us are
sector 0, the boot sector, and the sectors immediately following it -
the FAT's.

COUNT is the number of sectors to read.

So, to read in the first 10 sectors of the FAT on my E: partition (the
FAT starts at sector 1), storing them at 0200, I would enter

l 0200 4 0 A

Writing is done with the W command, which takes the same
parameters. Assuming I had edited the boot sector of E: at 0200 in memory,
and wanted to write it back to disk, I would type in

w 0200 4 0 1

Using Norton Utilities NU:

<E>xplore disk, <C>hoose Item, <S>ector, <E>dit/display

Unfortunately, absolute sector 0 falls outside of all partitions (this
is where the partition table is), and we need to use a different
procedure for it.

Reading / Writing absolute sector 0:
The following debug / assembler interaction shows how to read absolute disk
sector 0 , replace xx with 80 for hard disk 0, 81 for hard disk 1:

-a 0100
1984:0100 mov ax, 0201
1984:0103 mov bx, 0200
1984:0106 mov cx, 0001
1984:0109 mov dx, 00xx
1984:010C int 13
1984:010E int 20
1984:0110 ^C