A Linux + Windows Laptop War Story

Peter Klausler

Initial configuration

I have a Gateway Solo 2100 laptop that I purchased in January 1997. Here's its initial relevant hardware configuration information:

I use this laptop both at home and at the office. When I'm at work, it has a static IP address for its assigned hostname. And at home, I have PPP connections to work and to my ISP.

The single C: partition on the 2.1GB hard drive was roughly 3/4 full at the beginning of this process.

Goal

Three years later (January 2000), I wanted to upgrade the hard drive to a larger device. More important, I also wanted to install Linux side-by-side with my existing Windows '95 environment. I did not want to reinstall Windows or any other software that was already installed and working.

On a desktop machine, this would be nearly trivial. I would just add a second hard drive to the system and install Linux on it. However, this laptop can only have one hard drive installed at a time. This is the primary constraint. A lesser problem is that this laptop cannot have its floppy drive and its CD-ROM drive installed simultaneously; they compete for the single modular drive bay.

Basic Plan

I bootstrapped my way from the initial configuration to my desired configuration as follows:

This plan made sense, but this would be a very dull war story if it had proceeded as easily as I had thought that it would!

Squeezing Linux into the existing environment

Preparation

Paranoia

The first step, of course, was to make full backups of my existing Windows system. I used Iomega's bundled "1-Step Backup and Restore" tools to back things up to ZIP disks. I usually do full backups of everything except software that was installed from a CD-ROM or downloaded from Internet sites. I keep original downloaded software packages on ZIP disks after installation, so I don't bother backing up their expanded files.

Notetaking

Next, I got hard copy output of my current system configuration from the System icon tool in the Windows Control Panel. I also printed off all of my networking configuration information. I connected to both of my dial-up PPP servers with modem logging enabled and printed the logs. And I fired up the Outlook '98 mail client for one last time to make sure that I had the right host names, accounts, and passwords for my various POP3/IMAP mail servers.

One should really have all of this information handy anyway, I suppose.

Checking the Web

I checked the excellent Linux on Laptops HOWTO file at the invaluable web page of the Linux Documentation Project. There was no record of an installation on a Gateway Solo 2100, but there were success stories from some later models.

I figured that so long as I didn't do anything irrevocable, it was worth a try.

Getting Linux

Armed with a $25.00 gift certificate card received for Christmas, I visited my local chain-store megabookstore and purchased a copy of "Red Hat Linux for Dummies" that came with Red Hat Linux 6.1 binaries and sources on two CD-ROMs.

Printing HOWTOs

I printed hard copies of several pertinent HOWTO files from the Linux Documentation Project.

Making Space

After voiding out my deleted mail folder, deleting some obviously needless files, uninstalling some needless software, and then emptying the Recycle Bin, I got my C: drive down to a little over 800 MB of occupied space.

The next step, which proved to be the hardest of the whole story, was compacting the Windows data into the initial 800 MB of space on the drive. I first naively ran the bundled disk defragmentation tool from the Tools tab of the Properties dialog of the C: drive in My Computer. This program is nearly hypnotic to watch when run with its "Show Details" graphical output.

The Windows defragmenter moved almost all of my data snugly into the initial area of the C: partition. However, there were numerous blocks owned by "hidden" and "system" files that it refused to touch. These blocks are signified by the hollow red square icons, and I groaned when I saw them remain scattered around the end of the C: partition in the graphical display.

I suppose that there are probably better disk defragmentation programs available for DOS partitions that would do a complete job, but I refused to spend more money for a DOS utility than I was about to spend for an entire new operating system. So I had to move these "hidden" and "system" files' blocks some other way.

Booting DOS from a floppy, I located all of the "hidden" and "system" files on the C: partition using DIR C:\ /S /A:H, DIR C:\ /S /A:S, and DIR C:\ /S /A:HS commands with output redirected to files. I compacted these listings together and printed them.

I realized that I could move the contents of a "hidden" or "system" file by copying its data to new blocks on the disk, which would be allocated from the beginning of the drive's free space. This was laborious, but straightforward. Visiting each of these files in turn from the DOS prompt, I:

This took a while. I then rebooted Windows and re-ran the disk defragmentation utility.

And several blocks were still left standing with hollow red icons at the end of the drive. But there were fewer of them, so I knew that I was making progress.

I thereby learned that the DOS DIR /S command does not descend into hidden directories, although it does list their names if searching for /A:H files. Fed up with the whole stupid notion of "hidden" files, I ran ATTRIB /S -H recursively on the whole damn C: partition and then scanned again for "system" files. I then moved the newly discovered ones with the technique described above, rebooted Windows, and re-ran the disk defragmentation utility.

Several blocks were still left standing with hollow red icons at the end of the drive. By this time, I had learned to scroll down to the end of the drive in the graphical display of the defragmentation program and stare at that last allocated block, hoping that it would not transform itself from a dark green block to a hollow red square... and moaning when it did.

Clearly these blocks could not be part of a "system" or "hidden" file, or be part of a "hidden" directory. They must belong to a "system" directory itself. Walking through my list of these files, I identified the "system" directories and moved them with the laborious technique of removing their "system" attribute, renaming them, creating a new directory with the original name, copying the contents of the original directory into the new directory, and reenabling their "system" attribute.

I rebooted Windows, re-ran the disk defragmentation utility, and cursed when I saw one red hollow block remaining at the end of the drive.

I had a pretty good guess that it belonged to my Internet Explorer "Favorites" folder. Why? I had installed Internet Explorer 4.0 at a time when my disk had been nearly full, and all of the other "system" directories had much earlier times of last modification back when the laptop was new. I tried renaming that folder to something else and creating a new, empty "Favorites" folder. And I was shocked when I rebooted Windows and found that it had moved the files back! This was very spooky.

Realizing that Windows must play some games with the file system below the level of the directory structure in order to put per-user personalized directories into standard locations, I then tried rebooting Windows and logging in as a new user with a throwaway account name. This did the trick, and I was then able to apply the rename/copy/reenable technique successfully to these last "system" directories. After ten hours of frustration, I got a clean disk defragmentation run, and all of my data was compacted.

In retrospect, I probably should have just acquired a better defragmentation tool and saved this time. Of course, I was my fault in the first place for using an operating system (Windows '95) that doesn't ship with adequate utilities, even when you've paid good money for it.

Repartitioning with fips

I set up a temporary folder and copied the contents of the DOS utility folder on the Red Hat CD-ROM into it. Then I powered down the laptop, swapped the CD-ROM drive with the floppy drive, and constructed a bootable DOS floppy disk with FORMAT A: /S. I copied the Red Hat DOS utilities onto it, along with the FORMAT.COM and FDISK.EXE programs from Windows.

Rebooting DOS from the floppy, I then ran the excellent fips utility. Using the left arrow key, I reduced the size of the primary DOS partition (C:) down to a gigabyte. The fips tool refuses to reduce a partition below its last allocated sector and also performs a bunch of sanity checks. It then created a new partition on the hard drive that occupies the latter half of the drive.

I then rebooted Windows and ran some sanity checks. The C: drive was the right size, and it saw the second partition correctly and called it D:.

Installing Linux

Now for the fun part! I powered down the laptop and swapped the CD-ROM drive into the modular bay, with the Red Hat install disk still in the drive. Powering back up, I held down the F2 key and entered the BIOS Setup program. I configured the BIOS to boot from the CD-ROM, saved the configuration, and proceeded with the boot.

Red Hat's install tool came up. I tried its graphical interface, but the default X configuration that it uses did not work on my machine. The display was scrambled. So I rebooted and typed text to use the installation tool's textual interface.

Installing Red Hat was straightforward. I deleted the spare DOS partition and then partitioned my free gigabyte into:

It took a couple of tries to get X configured correctly. The right choice was tell it that the display was "extended super VGA" with 800x640 and 640x480 modes, 1 MB of VRAM, and enabling just the 800x640 8-bit color mode.

Linux then halted and the laptop began to reboot. I held the F2 key down to get back into the BIOS Setup program, and reconfigured the BIOS to boot from the usual sources "A: then C:", rather than from the CD-ROM drive. I saved this restored configuration, proceeded with the reboot, and was soon rewarded with a UNIX login prompt. I checked that my Windows files were accessible from the VFAT partition that I mounted on /mnt/dos, and all was well. I had established the UNIX beachhead on my machine.

Bringing up Linux in the laptop environment

At a minimum, I had to get NFS working with my employer's file server before I could upgrade to a larger hard drive. This would make it much easier to transfer the existing Windows partition. And getting NFS working implied that networking over my PCMCIA Ethernet adapter was working.

However, I had some time to wait before my new larger hard disk drive arrived. This was due to ordering the wrong drive, and having to send it back while re-ordering the right drive from NECX Direct. I was somewhat disappointed that the largest upgrade drive for the Gateway Solo 2100 was only 4 GB, not the 6 GB that I had already allocated in my mind. Anyway, I proceeded to make my initial Linux environment fully functional while still on the original 2.1 GB drive, but in principle I could have deferred much of this work until I was up and running on the larger disk.

PCMCIA

Enabling PCMCIA turned out to be a small change. I edited /etc/sysconfig/pcmcia to read

PCMCIA=yes
PCIC=i82365
and rebooted.

ZIP

Red Hat Linux 6.1 ships with the "ppa" parallel port agent module needed to recognize an Iomega parallel port ZIP drive as a fake SCSI device, but it needs to be installed as a dynamic kernel module. Using another init.d script as a template, I wrote this script and put it into /etc/rc.d/init.d/ppa:


#!/bin/sh

usage()
{
    echo "Usage: $0 {start|stop|restart}"
}

EXITCODE=1
for x in "1" ; do

    if [ $# -lt 1 ] ; then usage ; break ; fi
    action=$1

    case "$action" in

    'start')
	echo -n "Starting PPA services:"
	if fgrep -q "ppa " /proc/modules
	then	true
	else	if fgrep -q "parport " /proc/modules
		then	echo -n " parport(present)"
		else	echo -n " parport"
			/sbin/insmod parport
			/sbin/insmod parport_probe
			/sbin/insmod parport_pc
		fi
		echo -n " ppa"
		/sbin/insmod ppa
	fi
	if [ -d /var/lock/subsys ] ; then
	    touch /var/lock/subsys/ppa
	fi
	echo "."
	;;

    'stop')
	echo -n "Shutting down PPA services:"
	if fgrep -q "ppa " /proc/modules ; then
	    echo -n " ppa"
#	    /sbin/rmmod ppa
	fi
	echo "."
	rm -f /var/lock/subsys/ppa
	EXITCODE=0
	;;

    'restart')
	$0 stop
	$0 start
	EXITCODE=0
	;;

    *)
	usage
	;;

    esac

done

# Only exit if we're in our own subshell
if [ "${0##*/}" = "rc.ppa" ] ; then
    exit $EXITCODE
fi

I also put a symbolic link into /etc/rc.d/rc5.d so that the parallel port agent would be activated on normal boots via:

cd /etc/rc.d/rc5.d
ln -s ../init.d/ppa S55ppa

Ethernet networking

Once my 3Com PCMCIA Ethernet adapter was accessible as a PCMCIA device, getting on to the corporate network with my old assigned static IP address was straightforward with the GNOME System Control Panel's networking configuration tool.

There is one unfortunate aspect to that tool: it's only available if you logged in initially as root. There's no way to get to it if you log in as yourself and then want to su - to root.

NFS

After a gracious system administrator agreed to export the NFS partition containing my home directory on the corporate file server to my Linux host, I simply added an NFS line to /etc/fstab and mounted it.

fileserver:/export/partition /mnt/partition nfs rsize=8192,wsize=8192,user,exec,nodev,rw 0 0

I then realized that I would have to use the same UNIX user number and group numbers on my Linux laptop that the company uses on its file server. So I changed the user number of my regular login account in /etc/passwd and added some entries to /etc/group, and then ran find / -uid 500 -print0 | xargs -0 chown user:group to reflect the change.

Dial-up networking

Establishing a dial-up PPP connection to my ISP was also straightforward with the GNOME tools. I found the chat script it created in /etc/sysconfig/network-scripts by running find /etc -type f -print0 | xargs -0 egrep -l phone number and its associated interface configuration file in the same directory.

Establishing a dial-up PPP connection to my employer was complicated by the fact that we do not use static passwords, but instead have passwords that change every minute or so. I have a little box with an LCD display of my current password. So I had to hack the ifup- script to build a new chat script on each dial-up attempt using a password stored in a new publically-writable file, and wrote another script for /root/bin that tries to fire up the PPP connection in the background while diverting its standard input to that file. It's ugly, but it works.

Mail

Rather than using a POP3 or IMAP mail client and having to deal with their restrictions on using multiple servers, I get my mail from my corporate mail server and my ISP by using fetchmail to grab the mail and divert it to sendmail on the laptop for local delivery. It was pretty easy to construct a $HOME/.fetchmailrc file to do this by reading the fetchmail man page.

One complication: although my two PPP connections are named ppp0 and ppp1, networking always calls the active interface ppp0 if either of them is up.

Getting sendmail to send my outgoing mail to the right place was a little trickier; remember that I'm sometimes at work connected via Ethernet to the LAN, and sometimes I'm at home connected to work via PPP, and sometimes I'm connected to my ISP via PPP from home. I installed the sendmail-cf package with rpm -i from the Red Hat CD-ROM and hacked together a solution.

First, I made sure that my host name was in /etc/sendmail.cw. Next, I added these lines


FEATURE(genericstable,`hash -o /etc/mail/genericstable')
define(`SMART_HOST',include(`/etc/mail/smarthost'))
GENERICS_DOMAIN_FILE(`/etc/mail/genericsdomain')
MAILER(local)

to /etc/sendmail.cf. In /etc/mail, I set up a couple of genericstable.configuration name files to map my login and root to my e-mail addresses at work and at my ISP.

Last, I wrote a script /etc/mail/mailconfig that uses its argument to put the name of the right outgoing SMTP server into /etc/mail/smarthost, generate a new /etc/sendmail.cf file with m4 from /etc/sendmail.mc, run makemap hash to generate a new hashed /etc/mail/genericstable.db, and restart the sendmail daemon.

My PPP connection scripts in /root/bin invoke this /etc/mail/mailconfig script whenever they connect. It also gets run when I log in or when the laptop resumes execution after snoozing in low-power mode.

Downloading

I don't have to tell you that there are piles of great free software for x86 Linux available on the World Wide Web. I keep downloaded packages in /var/download until I can migrate them off to a ZIP disk for backup purposes. I downloaded Adobe's Acrobat reader, the latest Enlightenment window manager and the tools on which it depends, and a bunch of cool themes from themes.org. I also downloaded some disappointing checkbook management tools, but didn't keep them.

Interlude

I ran with Windows and Linux in a multi-boot environment for several weeks before proceeding to upgrade my hard disk drive. I remained very impressed with Linux and the GNOME/Enlightenment environment. I configured my laser printer and connections to laser printers in my work environment.

Migrating Windows data

I migrated my old saved mail from Outlook into ELM-readable mail files by exporting the folders from Outlook and running them through a custom filter program. And I exported my checkbook data from Microsoft Money to a Quicken Interchange Format file, fixed the Y2K problems with dates after 1/1/2000, and wrote a basic checkbook utility that operates on QIF files under Linux.

Upgrading the hard drive

Getting the drive

As I mentioned, I screwed up the initial order for a larger hard disk drive, but on my second attempt I was able to wake up and find a box from UPS on my front porch with the right part in it. I packed my ZIP drive, floppy drive, spare disks, backups, and a screwdriver into my bag and drove in to work.

Backing up Linux

I wrote a simple script to back up my home directory and modified system files to compressed files in a mirror directory hierarchy on a ZIP disk. I tested it and made sure that I could re-install Linux on the new drive, re-install downloaded software, and restore my other files.

Of course, before I could restore files from the ZIP drive, I had to be able to get to the ZIP drive again from Linux. So I also wrote a floppy disk with all of the system files that I had added or changed.

Backing up Windows

My ZIP drive holds only 100 MB, but my old Windows partition nearly filled a gigabyte. So I went into work and borrowed some disk space from my employer for an hour or so.

I unmounted my DOS partition (/mnt/dos) and mounted my NFS partition. As root, I enabled world read access on my raw DOS partition (/dev/hda1). Then, using my normal login, I ran dd if=/dev/hda1 | gzip >/mnt/NFS home directory/hda1.gz. This took about half an hour, and the resulting file was about half a gigabyte long.

Swapping drives

I unscrewed the three screws holding my old 2.1 GB hard disk drive in its slot on the side of the laptop and gingerly pulled it out. I then took my new 4 GB hard disk drive out of its protective wrapper and compared them. They looked like they had the same form factor and connector. I put the old drive into the protective wrapping.

The new hard drive fit snugly into the slot. I didn't bother to screw it into place, since I was sure that I would be swapping drives to get data from the old one that I had forgotten to save on ZIP and floppy disks. And it did turn out to be necessary to swap the drives a couple of times, but I'll spare you the details. Once everything was done and working, I screwed the three screws back in, of course.

Re-installing Linux

I had to do this twice, since I forgot to format the new drive with the DOS FDISK program first. I used FDISK from my bootable DOS floppy to create two 2 GB DOS partitions, FORMAT to format them, and fips to adjust the size of the first partition to 1.5 GB. That's where Windows would go later.

I then power-cycled to swap in the CD-ROM drive, adjusted the BIOS as mentioned above to boot from the CD-ROM, and re-installed Linux. I created nice large partitions and separated /usr/local from /usr. I power-cycled, swapped the floppy drive back into the modular bay, restored the BIOS setting to boot from disk, and it booted.

I then recapitulated all of the reconfiguration changes mentioned above, using the new and modified files that I had saved to floppy and to ZIP disk. Soon I was back on the network with the right UNIX user number and able to copy my compressed Windows partition image back from NFS to a file in one of my nice large filesystems. I then made sure to delete the file from NFS so that all of my old Windows files wouldn't end up on a corporate backup tape.

Restoring Windows

I piped the output of zcat to dd of=/dev/hda1 to put the Windows filesystem image into its new 1.5 disk partition. But it wouldn't boot. The LILO loader could find it okay, but DOS would complain about an invalid system disk.

Learning all about boot sectors

It turns out that geometry (head, sector, and cylinder counts) of a disk is reflected in the first sector of a DOS partition. BIOS calls are in head/sector/cylinder coordinates, not simple sector offsets. Worse, DOS does not get disk geometry information from BIOS, but it is instead part of the "boot sector" code that is read from the first 512-byte sector of a bootable partition.

It also turned out that my new 4 GB hard drive had a different geometry than the 2.1 GB drive that it replaced. It wasn't just a matter of having more cylinders, but also more (presumably virtual) heads.

I located a Web page that explained the layout of DOS boot sectors and studied it until I was confident that I could adjust a few values (heads and total sectors) and get a working system. The per-cluster file allocation tables (FATs) were already large enough for a 1.5 GB partition, since they had covered the original drive's 2.1 GB extent before fips shrank it. Nothing needed to be moved around from sector to sector and no sector offsets needed to be adjusted.

So I booted Linux and dd'ed the first 512 bytes of /dev/hda1 to a temporary file. Note that that's the boot sector of the first partition, not the master boot record! After making a backup copy of the boot sector, I used the GNOME hex editor to change the number of heads from 128 to 240, and the total extent of the partition to 1.5 GB worth of 512-byte sectors, remembering that when I had adjusted that first partition with fips that I had set its size exactly equal to 200 cylinders.

I dd'ed it back into the boot sector, shut down, and booted Windows cleanly. The properties of the C: drive looked right, and I ran the disk scanning tool cleanly. I even ran the defragmentation tool, and noticed that the new drive was significantly faster than the old one had been.

Summary

Red Hat Linux 6.1 runs great on this older laptop, and looks great too. My processor is several generations out of date, and my display resolution is much less than modern high-end laptops, but this is a great UNIX/X platform notwithstanding. I'll get a couple more years of life out of it in this configuration before replacing it with a new high-end machine.

I've been using UNIX in various flavors (System V, BSD 4.2, SunOS, Solaris, UNICOS, UNICOS/mk, and IRIX) since the VAX days (1984) as a user, administrator, and developer. I am very impressed with the ease of installation, configuration, and use of the Red Hat 6.1 distribution. I simply can't believe that such high-quality software is available with source code for free.

Getting to a multi-boot environment was no big deal, apart from disk defragmentation woes that I could have avoided with better DOS tools. Upgrading the hard drive and restoring the Windows data required some resourcefulness and a willingness to use a hex editor, but the risk was low. Remember, all of my original data was still on my old 2.1 GB drive (and backup media).