From 1b761836a33cf51efb36c404b73c735a76df1abb Mon Sep 17 00:00:00 2001 From: Brian Palmer Date: Tue, 7 Aug 2001 05:37:13 +0000 Subject: [PATCH] Simple Win32 boot sector installer. Will not work under Win9x. svn path=/trunk/; revision=2158 --- freeldr/install/Makefile | 49 ++++++++++ freeldr/install/install.c | 189 ++++++++++++++++++++++++++++++++++++++ freeldr/install/install.h | 24 +++++ freeldr/install/volume.c | 135 +++++++++++++++++++++++++++ freeldr/install/volume.h | 29 ++++++ 5 files changed, 426 insertions(+) create mode 100644 freeldr/install/Makefile create mode 100644 freeldr/install/install.c create mode 100644 freeldr/install/install.h create mode 100644 freeldr/install/volume.c create mode 100644 freeldr/install/volume.h diff --git a/freeldr/install/Makefile b/freeldr/install/Makefile new file mode 100644 index 00000000000..9d867c5a250 --- /dev/null +++ b/freeldr/install/Makefile @@ -0,0 +1,49 @@ +# +# FreeLoader +# Copyright (C) 1999, 2000, 2001 Brian Palmer +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + + +export CC = gcc +export LD = ld +export AR = ar +export RM = cmd /C del +export CP = cmd /C copy +export NASM = nasm +export MAKE = make + +FLAGS = -Wall + +OBJS = install.o volume.o + +LIBS = -lkernel32 + +.PHONY : clean + +all: install.exe + +install.exe: $(OBJS) + $(CC) $(FLAGS) -o install.exe $(OBJS) + +install.o: install.c install.h volume.h + $(CC) $(FLAGS) -o install.o -c install.c + +volume.o: volume.c volume.h install.h + $(CC) $(FLAGS) -o volume.o -c volume.c + +clean: + \ No newline at end of file diff --git a/freeldr/install/install.c b/freeldr/install/install.c new file mode 100644 index 00000000000..536dd49ff91 --- /dev/null +++ b/freeldr/install/install.c @@ -0,0 +1,189 @@ +/* + * FreeLoader - install.c + * + * Copyright (C) 2001 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include "install.h" +#include "volume.h" +#include "../bootsect/fat.h" +#include "../bootsect/fat32.h" + +BOOL BackupBootSector(LPCTSTR lpszVolumeName); +BOOL InstallBootSector(LPCTSTR lpszVolumeType); + +int main(int argc, char *argv[]) +{ + + if (argc < 3) + { + _tprintf(_T("syntax: install x: [fs_type]\nwhere fs_type is fat or fat32\n")); + return -1; + } + + if (!OpenVolume(argv[1])) + { + return -1; + } + + BackupBootSector(argv[1]); + + InstallBootSector(argv[2]); + + _tprintf(_T("You must now copy freeldr.sys & freeldr.ini to %s.\n"), argv[1]); + + CloseVolume(); + + return 0; +} + +BOOL BackupBootSector(LPCTSTR lpszVolumeName) +{ + HANDLE hBackupFile; + TCHAR szFileName[MAX_PATH]; + ULONG Count; + BYTE BootSectorBuffer[512]; + DWORD dwNumberOfBytesWritten; + BOOL bRetVal; + + // + // Find the next unused filename and open it + // + for (Count=0; ; Count++) + { + // + // Generate the next filename + // + _stprintf(szFileName, _T("%s\\bootsect.%03d"), lpszVolumeName, Count); + + // + // Try to create a new file, fail if exists + // + hBackupFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, /*FILE_ATTRIBUTE_SYSTEM*/0, NULL); + + // + // Check to see if it worked + // + if (hBackupFile != INVALID_HANDLE_VALUE) + { + break; + } + + // + // Nope, didn't work + // Check to see if it already existed + // + if (!(GetLastError() != ERROR_ALREADY_EXISTS)) + { + _tprintf(_T("%s:%d: "), __FILE__, __LINE__); + _tprintf(_T("Boot sector backup failed. Error code %d.\n"), GetLastError()); + return FALSE; + } + } + + // + // Try to read the boot sector + // + if (!ReadVolumeSector(0, BootSectorBuffer)) + { + CloseHandle(hBackupFile); + return FALSE; + } + + // + // Try to write the boot sector data to the file + // + bRetVal = WriteFile(hBackupFile, BootSectorBuffer, 512, &dwNumberOfBytesWritten, NULL); + if (!bRetVal || (dwNumberOfBytesWritten != 512)) + { + CloseHandle(hBackupFile); + _tprintf(_T("%s:%d: "), __FILE__, __LINE__); + _tprintf(_T("WriteFile() failed. Error code %d.\n"), GetLastError()); + return FALSE; + } + + _tprintf(_T("Boot sector backed up to file: %s\n"), szFileName); + + CloseHandle(hBackupFile); + + return TRUE; +} + +BOOL InstallBootSector(LPCTSTR lpszVolumeType) +{ + BYTE BootSectorBuffer[512]; + + // + // Read in the old boot sector + // + if (!ReadVolumeSector(0, BootSectorBuffer)) + { + return FALSE; + } + + if (_tcsicmp(lpszVolumeType, _T("fat")) == 0) + { + // + // Update the BPB in the new boot sector + // + memcpy((fat_data+3), (BootSectorBuffer+3), 59 /*fat BPB length*/); + + // + // Write out new boot sector + // + if (!WriteVolumeSector(0, fat_data)) + { + return FALSE; + } + } + else if (_tcsicmp(lpszVolumeType, _T("fat32")) == 0) + { + // + // Update the BPB in the new boot sector + // + memcpy((fat32_data+3), (BootSectorBuffer+3), 87 /*fat32 BPB length*/); + + // + // Write out new boot sector + // + if (!WriteVolumeSector(0, fat32_data)) + { + return FALSE; + } + + // + // Write out new extra sector + // + if (!WriteVolumeSector(14, (fat_data+512) )) + { + return FALSE; + } + } + else + { + _tprintf(_T("%s:%d: "), __FILE__, __LINE__); + _tprintf(_T("File system type %s unknown.\n"), lpszVolumeType); + return FALSE; + } + + _tprintf(_T("%s boot sector installed.\n"), lpszVolumeType); + + return TRUE; +} diff --git a/freeldr/install/install.h b/freeldr/install/install.h new file mode 100644 index 00000000000..4a3a746d850 --- /dev/null +++ b/freeldr/install/install.h @@ -0,0 +1,24 @@ +/* + * FreeLoader - install.h + * + * Copyright (C) 2001 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __INSTALL_H +#define __INSTALL_H + +#endif // defined __INSTALL_H \ No newline at end of file diff --git a/freeldr/install/volume.c b/freeldr/install/volume.c new file mode 100644 index 00000000000..43a9dd3a762 --- /dev/null +++ b/freeldr/install/volume.c @@ -0,0 +1,135 @@ +/* + * FreeLoader - volume.c + * + * Copyright (C) 2001 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include "volume.h" + +static HANDLE hDiskVolume = NULL; + +BOOL OpenVolume(LPCTSTR lpszVolumeName) +{ + TCHAR RealVolumeName[MAX_PATH]; + + // + // If they passed in a drive letter (e.g. "A:") + // then try to open the physical device volume, + // otherwise we will assume it is a disk image + // file they are writing to. (not fully supported yet) + // + if ((_tcslen(lpszVolumeName) == 2) && (lpszVolumeName[1] == _T(':'))) + { + _tcscpy(RealVolumeName, _T("\\\\.\\")); + _tcscat(RealVolumeName, lpszVolumeName); + } + else + { + _tcscpy(RealVolumeName, lpszVolumeName); + } + + _tprintf(_T("Opening volume \'%s\'\n"), lpszVolumeName); + + hDiskVolume = CreateFile(RealVolumeName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + + if (hDiskVolume == INVALID_HANDLE_VALUE) + { + _tprintf(_T("%s:%d: "), __FILE__, __LINE__); + _tprintf(_T("Failed. Error code %d.\n"), GetLastError()); + return FALSE; + } + + return TRUE; +} + +void CloseVolume(void) +{ + CloseHandle(hDiskVolume); +} + +BOOL ReadVolumeSector(ULONG SectorNumber, PVOID SectorBuffer) +{ + DWORD dwNumberOfBytesRead; + DWORD dwFilePosition; + BOOL bRetVal; + + // + // FIXME: this doesn't seem to handle the situation + // properly when SectorNumber is bigger than the + // amount of sectors on the disk. Seems to me that + // the call to SetFilePointer() should just give an + // out of bounds error or something but it doesn't. + // + dwFilePosition = SetFilePointer(hDiskVolume, (SectorNumber * 512), NULL, FILE_BEGIN); + if (dwFilePosition != (SectorNumber * 512)) + { + _tprintf(_T("%s:%d: "), __FILE__, __LINE__); + _tprintf(_T("SetFilePointer() failed. Error code %d.\n"), GetLastError()); + return FALSE; + } + + bRetVal = ReadFile(hDiskVolume, SectorBuffer, 512, &dwNumberOfBytesRead, NULL); + if (!bRetVal || (dwNumberOfBytesRead != 512)) + { + _tprintf(_T("%s:%d: "), __FILE__, __LINE__); + _tprintf(_T("ReadFile() failed. Error code %d.\n"), GetLastError()); + return FALSE; + } + + return TRUE; +} + +BOOL WriteVolumeSector(ULONG SectorNumber, PVOID SectorBuffer) +{ + DWORD dwNumberOfBytesWritten; + DWORD dwFilePosition; + BOOL bRetVal; + + // + // FIXME: this doesn't seem to handle the situation + // properly when SectorNumber is bigger than the + // amount of sectors on the disk. Seems to me that + // the call to SetFilePointer() should just give an + // out of bounds error or something but it doesn't. + // + dwFilePosition = SetFilePointer(hDiskVolume, (SectorNumber * 512), NULL, FILE_BEGIN); + if (dwFilePosition != (SectorNumber * 512)) + { + _tprintf(_T("%s:%d: "), __FILE__, __LINE__); + _tprintf(_T("SetFilePointer() failed. Error code %d.\n"), GetLastError()); + return FALSE; + } + + bRetVal = WriteFile(hDiskVolume, SectorBuffer, 512, &dwNumberOfBytesWritten, NULL); + if (!bRetVal || (dwNumberOfBytesWritten != 512)) + { + _tprintf(_T("%s:%d: "), __FILE__, __LINE__); + _tprintf(_T("WriteFile() failed. Error code %d.\n"), GetLastError()); + return FALSE; + } + + return TRUE; +} diff --git a/freeldr/install/volume.h b/freeldr/install/volume.h new file mode 100644 index 00000000000..4155429a823 --- /dev/null +++ b/freeldr/install/volume.h @@ -0,0 +1,29 @@ +/* + * FreeLoader - volume.h + * + * Copyright (C) 2001 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __VOLUME_H +#define __VOLUME_H + +BOOL OpenVolume(LPCTSTR lpszVolumeName); +void CloseVolume(void); +BOOL ReadVolumeSector(ULONG SectorNumber, PVOID SectorBuffer); +BOOL WriteVolumeSector(ULONG SectorNumber, PVOID SectorBuffer); + +#endif // defined __VOLUME_H