Deutsch   English   Français   Italiano  
<vpgghn$o45q$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail
From: Ben Collver <bencollver@tilde.pink>
Newsgroups: comp.misc
Subject: The DOS 3.3 SYS.COM Bug Hunt
Date: Mon, 24 Feb 2025 01:03:51 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 508
Message-ID: <vpgghn$o45q$1@dont-email.me>
Injection-Date: Mon, 24 Feb 2025 02:03:52 +0100 (CET)
Injection-Info: dont-email.me; posting-host="86678114f43cf0d9fa069856e9289d00";
	logging-data="790714"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX1/8Hp8TnWxmIWPNBX128XLwp8f77GbnDD8="
User-Agent: slrn/1.0.3 (Linux)
Cancel-Lock: sha1:Xdq1MImfRwQ2vJG416udMqksHco=
Bytes: 22849

The DOS 3.3 SYS.COM Bug Hunt
============================
SYS.COM corrupted a NetDrive image. But why?

Posted: 2025-02-22
Tags: DOS, NetDrive, ForgotToCheckReturnCode

In ye olden days to make a diskette bootable you had to format it
using the /s option of the FORMAT command. That works fine for blank
disks, but software vendors had a small problem--they would sell you
a disk with their software on it but they couldn't include the DOS
files needed to make it bootable because they were not selling you
DOS. To get around this they would leave space available on the disk
and have you use the SYS command, which copied the magic boot loader
code onto from your DOS disk onto their disk. There were some
restrictions on where the free space was located and how much was
required, but it generally worked to allow you to make a diskette
bootable without having to format it.

Last year somebody reported a problem with the DOS 3.3 SYS.COM
command when used with NetDrive. They started with a valid FAT12
image, ran SYS.COM to make it bootable, and then they were not able
to mount the image using NetDrive again. Running SYS.COM against the
image had broken something.

Besides copying the operating system's hidden files to the target
drive letter, SYS.COM also copies some boot code into the first
sector of the disk. In general it does not make sense to run it
against a NetDrive image because you already had to boot DOS to mount
the image, but it should not hurt anything. So I decided to have a
look at what was going on.

The first step was to recreate the problem. I created a 10MB FAT12
disk image using NetDrive. The first few bytes of the first sector
(the volume boot record) are shown below:


The FAT12 NetDrive image when first created:

00000000 EB 3C 90 4E  45 54 44 52  49 56 45 00  02 08 01 00 .<.NETDRIVE.....
00000010 02 00 02 00  50 F8 60 00  00 00 00 00  00 00 00 00 ....P.`.........
00000020 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00 ................

<... snip ...>

000001E0 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00 ................
000001F0 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00 ................

00000200 F8 FF FF 00  00 00 00 00  00 00 00 00  00 00 00 00 ................


Dissecting that we find:

    Offset  Bytes                    Description
    ------  -----------------------  ------------------------------------
    0x00    EB 3C 90                 Jump to executable code
    0x03    4E 45 54 44 52 49 56 45  OEM ID ("NETDRIVE")
    0x0B    00 02                    Bytes per sector (512)
    0x0D    08                       Sectors per cluster (8)
    0x0E    01 00                    Reserved sectors (1)
    0x10    02                       Number of File Allocation Tables (2)
    0x11    00 02                    Root directory entries (512)
    0x13    00 50                    Sectors (20480)
    0x15    F8                       Media Descriptor (hard drive)
    0x16    60 00                    Sectors per fat (6)

That is a minimal BIOS Parameter Block (BPB) as defined by DOS 2.0
but also recognizable to later versions of DOS. Later versions of DOS
have extended it a few times.

At offset 0x200 you see the start of the first File Allocation Table
(FAT). The first byte 0xF8 is the media descriptor byte, which should
be the same as the one in the BPB. This is FAT12 so entries are 12
bits in size; the first entry is actually 0xF8F and the second entry
is 0xFFF. Ignoring the media descriptor entry and the second entry
which is reserved, this FAT is completely empty.

I mounted the new image under IBM PC DOS 3.3 and ran SYS.COM against
it. That looked normal. However, when I disconnected the image and
tried to mount it again NetDrive complained that it was a bad image:

    C:\MTCP>sys e:
    System transferred
    
    C:\MTCP>netdrive disconnect e:
    mTCP NetDrive by M Brutman (mbbrutman@gmail.com) (C)opyright 2008-2025
    Version: Feb 17 2025
    
    NetDrive device opened, IOCTL_read return code: 8 0A1E:0020 0A1E:1768
    
    Drive disconnected from network.
    Server session (54559) ended
    
    C:\MTCP>netdrive connect calculon:2002 small.dsk e:
    mTCP NetDrive by M Brutman (mbbrutman@gmail.com) (C)opyright 2008-2025
    Version: Feb 17 2025
    
    NetDrive device opened, IOCTL_read return code: 8 0A1E:0020 0A1E:1768
    
    Resolving calculon, press [ESC] to abort.
    Server ip address is: 192.168.2.101
    Next hop address: 98:90:96:C3:14:70
    Error opening virtual hard drive: small.dsk,
      bad BPB and file size doesn't match a 170K or 320K DOS 1.x disk
    
    C:\MTCP>_

Well, the BPB started off correctly but now it seems bad. Let's look
at the first sector now that SYS.COM has altered it:

00000000 EB 34 90 49  42 4D 20 20  33 2E 33 00  02 3B C1 75 .4.IBM  3.3..;.u
00000010 1A 8B 16 DC  09 8B 0E DE  09 2B CA 74  D4 8B 1E 00 .........+.t....
00000020 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 12 ................
00000030 00 00 00 00  01 00 FA 33  C0 8E D0 BC  00 7C 16 07 .......3.....|..
00000040 BB 78 00 36  C5 37 1E 56  16 53 BF 2B  7C B9 0B 00 .x.6.7.V.S.+|...

<... snip ...>

000001C0 0D 0A 44 69  73 6B 20 42  6F 6F 74 20  66 61 69 6C ..Disk Boot fail
000001D0 75 72 65 0D  0A 00 49 42  4D 42 49 4F  20 20 43 4F ure...IBMBIO  CO
000001E0 4D 49 42 4D  44 4F 53 20  20 43 4F 4D  00 00 00 00 MIBMDOS  COM....
000001F0 00 00 00 00  00 00 00 00  00 00 00 00  00 00 55 AA ..............U.

00000200 F8 FF FF 03  40 00 05 60  00 07 F0 FF  09 A0 00 0B ....@..`........
00000210 C0 00 0D E0  00 0F F0 FF  00 00 00 00  00 00 00 00 ................

    Offset  Bytes                    Description
    ------  -----------------------  -------------------------------------
    0x00    EB 34 90                 Jump to executable code
    0x03    49 42 4D 20 20 33 2E 33  OEM ID ("IBM 3.3")
    0x0B    00 02                    Bytes per sector (512)
    0x0D    3B                       Sectors per cluster (59)
    0x0E    C1 75                    Reserved sectors (49525)
    0x10    1A                       Number of File Allocation Tables (26)
    0x11    8B 16                    Root directory entries (35606)
    0x13    DC 09                    Sectors (56239)
    0x15    8B                       Media Descriptor (unknown)
    0x16    0E DE                    Sectors per fat (3806)

It makes sense for the jump instruction and OEM ID to change. And the
bytes per sector field is correct. But the rest of the BPB is
garbage. Something corrupted it.

Looking at the rest of the sector the boot code starts at offset 0x3E
and that looks reasonable. There is also the bootable partition
signature (0xAA55) at offset 0x1FE, and the FAT shows some additional
entries for the two hidden files that were copied over.

I tried it again, this time with a diskette image mounted using
NetDrive, and it did everything perfectly. Which implies that the
problem is not in NetDrive, but in the difference between hard drive
images and floppy disk images.

So the DOS 3.3 SYS command added the boot code and updated the FAT
correctly, but it clobbered the BPB. But only on the NetDrive hard
drive image. Why?

DOS 3.2 added a function called "Generic IOCTL" which allows DOS to
query a device to get its geometry, write a track, read a track,
format a track, etc It also added code to handle these additional
calls for the devices supported by the BIOS. For example, here is a
call to "Get Device Parameters" (Generic IOCTL, sub function 0x60)
for drive C:

    C:\DOS>debug
    -a
    18CE:0100 mov ax,440d
    18CE:0103 mov bl,03
    18CE:0105 mov cx,0860
    18CE:0108 mov dx,0400
    18CE:010B int 21
    18CE:010D int 20
    18CE:010F
    -g=100 10d
    
    AX=0001  BX=0003  CX=0860  DX=0400  SP=FFEE  BP=0000  SI=0000  DI=0000
    DS=18CE  ES=18CE  SS=18CE  CS=18CE  IP=010D   NV UP EI PL NZ NA PO NC
    18CE:010D CD20          INT     20
    -g
    
    Program terminated normally
    -d 400 l 30
    18CE:0400 89 05 01 00 41 00 00 00-02 04 01 00 02 00 02 B1 ....A...........
    18CE:0410 FF F8 40 00 3F 00 10 00-3F 00 FA 89 45 06 8B 46 ..@.?...?...E..F
    18CE:0420 FC 89 05 8B 46 EC 89 EC-5D 5F 5E C3 51 56 55 89 ....F...]_^.QVU.
========== REMAINDER OF ARTICLE TRUNCATED ==========