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
/* vim: set sts=4 sw=4: */
#include <windows.h>
#include <stdio.h>
#include <string.h>

#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();
}
_______________________________________________
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to