From owner-freebsd-questions@FreeBSD.ORG Thu Sep 13 21:00:05 2007 Return-Path: Delivered-To: freebsd-questions@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B132916A41A for ; Thu, 13 Sep 2007 21:00:05 +0000 (UTC) (envelope-from cb@severious.net) Received: from ion.gank.org (ion.gank.org [69.55.238.164]) by mx1.freebsd.org (Postfix) with ESMTP id 9280613C46A for ; Thu, 13 Sep 2007 21:00:05 +0000 (UTC) (envelope-from cb@severious.net) Received: by ion.gank.org (Postfix, from userid 1001) id 5827D118C9; Thu, 13 Sep 2007 16:00:05 -0500 (CDT) Date: Thu, 13 Sep 2007 16:00:04 -0500 From: Craig Boston To: Georgi Iovchev Message-ID: <20070913205954.GA5814@nowhere> Mail-Followup-To: Craig Boston , Georgi Iovchev , freebsd-questions@freebsd.org References: <1025711279.20070912121635@pulsar.bg> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="hQiwHBbRI9kgIhsi" Content-Disposition: inline In-Reply-To: <1025711279.20070912121635@pulsar.bg> User-Agent: Mutt/1.4.2.3i Cc: freebsd-questions@freebsd.org Subject: Re: how to change next boot from windows to freebsd? X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Sep 2007 21:00:05 -0000 --hQiwHBbRI9kgIhsi Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Wed, Sep 12, 2007 at 12:16:35PM +0300, Georgi Iovchev wrote: > Hello guys Hi. > But the problem is how to switch next boot when I am at windows via remote desktop??! I need something like boot0cfg but for windows, but it doesnt exist ) Attached is the source to a program that I wrote about 4 and a half years ago. It performs the function of a dumbed-down boot0cfg for Windows, only understanding the "-s" option, or giving you an interactive menu to choose from. It also is hardcoded to use PhysicalDrive0, but that's usually what you would boot from. I compile it using the devel/mingw32-gcc port. You can probably also use the version of mingw that's available through cygwin to compile it on the Windows side. Or you can be lazy and download the binary that I just posted to http://www.severious.net/nextboot.exe You should really compile it yourself though, rather than trusting random executables from strangers :-) I'll probably delete the binary after a week or so, but the source should live on in the list archives. The usual disclaimers: This program changes your MBR, I'm not responsible if it eats your partition table, your lunch, or your dog's lunch. Requires administrator rights to run. TT&L not included. Hope this helps, Craig --hQiwHBbRI9kgIhsi Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="nextboot.c" /* vim: set sts=4 sw=4: */ #include #include #include #define MBR_SIZE 512 #define OFF_VERSION 0x1b0 /* offset: version number */ #define OFF_OPT 0x1b9 /* offset: default boot option */ #define OFF_DRIVE 0x1ba /* offset: setdrv drive */ #define OFF_FLAGS 0x1bb /* offset: option flags */ #define OFF_TICKS 0x1bc /* offset: clock ticks */ #define OFF_PTBL 0x1be /* offset: partition table */ #define OFF_MAGIC 0x1fe /* offset: magic number */ #define DOSPARTOFF 446 #define NDOSPART 4 struct dos_partition { unsigned char dp_flag; /* bootstrap flags */ unsigned char dp_shd; /* starting head */ unsigned char dp_ssect; /* starting sector */ unsigned char dp_scyl; /* starting cylinder */ unsigned char dp_typ; /* partition type */ unsigned char dp_ehd; /* end head */ unsigned char dp_esect; /* end sector */ unsigned char dp_ecyl; /* end cylinder */ unsigned int dp_start; /* absolute starting sector number */ unsigned int dp_size; /* partition size in sectors */ }; int s_opt = 0; int mbrread = 0; unsigned char mbr[MBR_SIZE]; int errormsg(const char *msg) { LPVOID msgbuf; if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msgbuf, 0, NULL )) return 2; fprintf(stderr, "%s: %s\n", msg, (char*)msgbuf); LocalFree(msgbuf); return 1; } const char *getptype(unsigned char typ) { switch(typ) { case 0x1: case 0x11: return "FAT12"; case 0x2: return "Xenix root"; case 0x3: return "Xenix /usr"; case 0x4: case 0x14: return "FAT16 (Old school)"; case 0x5: return "DOS Extended"; case 0x6: case 0x16: return "FAT16"; case 0x7: case 0x17: return "NTFS"; case 0x8: return "OS/2 or AIX"; case 0x9: return "QNX"; case 0xa: return "OS/2 Boot Manager"; case 0xb: case 0x1b: return "FAT32"; case 0xc: case 0x1c: return "FAT32 LBA"; case 0xe: case 0x1e: return "FAT16 LBA"; case 0xf: return "Extended LBA"; case 0x12: return "Compaq Diagnostics"; case 0x18: return "AST Suspend-to-disk"; case 0x24: return "NEC DOS"; case 0x35: return "OS/2 Warp"; case 0x38: case 0x3a: return "THEOS"; case 0x39: return "Plan 9"; case 0x3c: return "PartitionMagic Recovery"; case 0x40: return "Venix"; case 0x41: case 0x42: case 0x43: return "DRDOS Cruft"; case 0x44: return "GoBack"; case 0x45: return "Boot-US"; case 0x46: case 0x47: case 0x48: return "EUMEL/Elan"; case 0x4a: return "AdaOS"; case 0x4c: case 0x4f: return "Oberon"; case 0x4d: case 0x4e: return "QNX"; case 0x50: return "OnTrack Disk Manager"; case 0x51: return "Novell"; case 0x52: return "CP/M"; case 0x53: return "Disk Manager"; case 0x54: return "Disk Manager Drive Overlay"; case 0x55: return "EZ-Drive"; case 0x56: return "Golden Bow DOS partition"; case 0x57: return "DrivePro"; case 0x61: return "SpeedStor"; case 0x63: return "Unix System V / Mach / GNU Hurd"; case 0x64: return "PC-ARMOUR"; case 0x65: case 0x67: case 0x68: case 0x69: return "Novell Netware"; case 0x70: return "DiskSecure"; case 0x74: return "Scramdisk"; case 0x75: return "IBM PC/IX"; case 0x78: return "XOSL"; case 0x80: case 0x81: return "Minix"; case 0x82: return "Linux swap"; case 0x83: return "Linux"; case 0x84: return "Hibernation"; case 0x85: return "Linux extended"; case 0x86: return "NTFS Volume Set"; case 0x87: return "NTFS Volume Set"; case 0x8a: return "Linux Kernel"; case 0x8b: return "FAT32 RAID"; case 0x8c: return "FAT32 RAID LBA"; case 0x8d: return "FreeDOS"; case 0x8e: return "Linux LVM"; case 0x90: case 0x91: case 0x92: case 0x97: case 0x98: case 0x9a: case 0x9b: return "FreeDOS"; case 0x93: return "Linux"; case 0x95: return "MIT EXOPC"; case 0x9f: return "BSD/OS"; case 0xa0: case 0xa1: return "Hibernation"; case 0xa5: return "FreeBSD"; case 0xa6: return "OpenBSD"; case 0xa7: return "NeXT"; case 0xa8: return "Mac OS X"; case 0xa9: return "NetBSD"; case 0xaa: return "Olivetti Service Partition"; case 0xab: return "Max OS X Boot Partition"; case 0xb0: return "BootStar"; case 0xb6: return "FAT16 Mirror Set"; case 0xb7: return "NTFS Mirror Set"; case 0xbb: return "Boot Wizard"; case 0xbe: return "Solaris 8 Boot Partition"; case 0xc0: return "CTOS"; case 0xc1: case 0xc4: case 0xc5: case 0xcb: case 0xcc: case 0xce: return "DRDOS"; case 0xc2: case 0xc3: return "Linux"; case 0xc6: case 0xc7: return "Windows NT corrupted volume set"; case 0xd0: return "REAL/32"; case 0xda: return "Data"; case 0xdb: return "Digital CP/M / Concurrent DOS"; case 0xde: return "Dell PowerEdge Utilities"; case 0xdf: return "DG/UX virtual disk manager"; case 0xe5: return "Tandy DOS"; case 0xeb: return "BeOS"; case 0xee: case 0xef: return "Microsoft/Intel EFI"; case 0xf0: return "Linux/PA-RISC"; case 0xf2: return "Unisys DOS"; case 0xf4: case 0xf5: return "Prologue"; case 0xfa: return "Bochs"; case 0xfb: return "VMWare File System"; case 0xfc: return "VMWare Swap"; case 0xfd: return "Linux RAID"; case 0xfe: return "Windows NT Hidden"; case 0xff: return "Xenix Bad Block Table"; default: return "Other"; } } int readmbr() { HANDLE disk; DWORD sz; disk = CreateFile("\\\\.\\PhysicalDrive0", GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); if (disk == INVALID_HANDLE_VALUE) return errormsg("Error accessing disk"); SetFilePointer(disk, 0, 0, FILE_BEGIN); if (!ReadFile(disk, mbr, MBR_SIZE, &sz, 0)) return errormsg("Error reading partition table"); CloseHandle(disk); if (sz != MBR_SIZE) { fprintf(stderr, "Error: Short read\n"); return 1; } mbrread = 1; return 0; } int verifybsd() { static unsigned char id0[] = {0xfc, 0x31, 0xc0, 0x8e, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc, 0x00, 0x7c }; static unsigned char id1[] = {'D', 'r', 'i', 'v', 'e', ' '}; static struct { unsigned off; unsigned len; unsigned char *key; } ident[2] = { {0x0, sizeof(id0), id0}, {0x1b2, sizeof(id1), id1} }; unsigned int i; if (!mbrread) { if (readmbr()) return 1; } if (mbr[OFF_MAGIC] != 0x55 || mbr[OFF_MAGIC+1] != 0xaa) { fprintf(stderr, "Error: MBR is not the FreeBSD boot manager\n"); return 1; } for (i = 0; i < sizeof(ident) / sizeof(ident[0]); i++) if (memcmp(mbr + ident[i].off, ident[i].key, ident[i].len)) { fprintf(stderr, "Error: Corrupt or unknown version of boot0\n"); return 1; } return 0; } int setnextboot(int n) { HANDLE disk; DWORD sz; if (!mbrread) { if (readmbr()) return 1; } if (verifybsd()) return 1; mbr[OFF_OPT] = n; disk = CreateFile("\\\\.\\PhysicalDrive0", GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (disk == INVALID_HANDLE_VALUE) return errormsg("Error accessing disk"); if (SetFilePointer(disk, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) return errormsg("Error seeking"); if (!WriteFile(disk, mbr, MBR_SIZE, &sz, 0)) return errormsg("Error writing to MBR"); CloseHandle(disk); if (sz != MBR_SIZE) { fprintf(stderr, "Error: Short write\n"); return 1; } return 0; } int menuboot() { struct dos_partition *part; int i; int pnum; char resp[256]; if (!mbrread) { if (readmbr()) return 1; } if (verifybsd()) return 1; printf("Please choose a partition for the next boot:\n\n"); part = (struct dos_partition*)(mbr + DOSPARTOFF); for (i = 0; i < NDOSPART; i++) if (part[i].dp_typ) { printf("%c%i. %s\n", (mbr[OFF_OPT] == i) ? '*' : ' ', i + 1, getptype(part[i].dp_typ)); } printf("\nSelect partition: "); fgets(resp, 255, stdin); if (!strlen(resp) || resp[0] == '\r' || resp[0] == '\n') return 0; pnum = atol(resp) - 1; if (pnum < 0 || pnum > 3 || !part[pnum].dp_typ) { fprintf(stderr, "Invalid partition\n"); return 1; } return setnextboot(pnum); } int usage() { fprintf(stderr, "Usage:\n\n" " nextboot (For interactive menu)\n\n" " nextboot [1-4] (Set partition to boot from)\n" " nextboot -s [1-4]\n" "\n"); return 0; } int main(int argc, char *argv[]) { int act; if (argc == 1) return menuboot(); else if ((argc == 2) && (strlen(argv[1]) == 1) && (argv[1][0] >= '1' && argv[1][0] <= '4')) { act = atol(argv[1]); return setnextboot(act - 1); } else if ((argc == 3) && !stricmp(argv[1], "-s") && (strlen(argv[2]) == 1) && (argv[2][0] >= '1' && argv[2][0] <= '4')) { act = atol(argv[2]); return setnextboot(act - 1); } return usage(); } --hQiwHBbRI9kgIhsi--