aboutsummaryrefslogtreecommitdiffstats
path: root/com32/modules/ifplop.c
blob: f502e2b3ec5c5e4b769990e6d317b74ae326e03a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/* ----------------------------------------------------------------------- *
 *
 *   Copyright 2010 Gert Hulselmans - All Rights Reserved
 *
 *   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, Inc., 51 Franklin St, Fifth Floor,
 *   Boston MA 02110-1301, USA; either version 2 of the License, or
 *   (at your option) any later version; incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

/*
 * ifplop.c
 *
 * This COM32 module detects if the PLoP Boot Manager was used to boot a CDROM
 * drive or USB drive, by checking for the presence of the PLoP INT13h hook.
 *
 * Usage:    ifplop.c32 [<plop_detected>] -- [<plop_not_detected>]
 * Examples: ifplop.c32 menu.c32 another.cfg -- plpbt hiddenusb usb1=2
 *              You need to remove the ".bin" extension of the plpbt.bin file
 *              if you use it this way.
 *           ifplop.c32 plop_detected -- plop_not_detected
 *
 * A possible config file could be:
 *
 * ===========================================================================
 *  DEFAULT plopcheck
 *
 *  # Check for the presence of PLoP (run by default)
 *  #   When PLoP INT13h hook is found, run the first command (plop_detected)
 *  #   When PLoP INT13h hook isn't found, run the second command (plop_not_detected)
 *  LABEL plopcheck
 *      COM32 ifplop.c32
 *      APPEND plop_detected -- plop_not_detected
 *
 *  # When PLoP INT13h hook was found, boot the menu system.
 *  # PLoP can have added USB 2.0 speed, so the entries we want to boot
 *  # will be read from disk much faster (supposing that we have a BIOS
 *  # that only supports USB 1.1 speed, but a mobo with USB 2.0 controllers).
 *  LABEL plop_detected
 *      COM32 menu.c32
 *      APPEND another.cfg
 *
 *  # PLoP INT13h hook wasn't found, so we boot PLoP, so it can add USB 2.0 support
 *  # When using "LINUX plpbt.bin", you don't need to remove the .bin extension.
 *  LABEL plop_not_detected
 *      LINUX plpbt.bin
 *      APPEND hiddenusb usb1=2
 *
 * ===========================================================================
 *
 * Why is/can this module be useful?
 *
 * You may want to boot PLoP by default from Syslinux when you boot from your
 * USB stick/drive:
 *   1. PLoP can upgrade USB 1.1 speed offered by the BIOS to USB 2.0 speed
 *      if you have USB 2.0 controllers on your mobo.
 *   2. Some BIOSes only can access the first 128GiB (137GB) on USB drives, while
 *      internal hard drives don't necessarily suffer from this 128GiB problem.
 *      Using PLoPs USB capabilities, you can access the whole drive.
 *
 * When you select the "USB" entry in PLoP, it will boot your USB stick/drive
 * again and it will boot PLoP again when you have set booting PLoP as DEFAULT
 * boot option in your Syslinux configuration file.
 *
 * By using ifplop.c32 you can specify which action you want to do the second
 * time your USB stick/drive is booted. So you can load another config file or
 * boot a large hard disk image or whatever you want.
 *
 * PLoP Boot Manager website: http://www.plop.at/en/bootmanager.html
 */

#include <com32.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <alloca.h>
#include <console.h>
#include <syslinux/boot.h>

static bool plop_INT13h_check(void)
{
    com32sys_t inregs, outregs;

    /* Prepare the register set */
    memset(&inregs, 0, sizeof inregs);

    /*
     * Check if PLoP already has booted a CDROM or USB drive by checking
     * for the presence of the PLoP INT13h hook.
     *
     * The following assembly code (NASM) can detect the PLoP INT13h hook:
     *
     *   mov eax,'PoLP'  ; Reverse of 'PLoP'
     *   mov ebp,'DKHC'  ; Reverse of 'CHKD'
     *   int 13h
     *   cmp eax,' sey'  ; Reverse of 'yes '
     *   jz plop_INT13h_active
     */

    inregs.eax.l = 0x504c6f50;	/* "PLoP" */
    inregs.ebp.l = 0x43484b44;	/* "CHKD" */

    __intcall(0x13, &inregs, &outregs);

    /* eax will contain "yes " if PLoP INT13h hook is available */
    if (outregs.eax.l == 0x79657320)
	return true;

    return false;
}

/* XXX: this really should be librarized */
static void boot_args(char **args)
{
    int len = 0, a = 0;
    char **pp;
    const char *p;
    char c, *q, *str;

    for (pp = args; *pp; pp++)
	len += strlen(*pp) + 1;

    q = str = alloca(len);
    for (pp = args; *pp; pp++) {
	p = *pp;
	while ((c = *p++))
	    *q++ = c;
	*q++ = ' ';
	a = 1;
    }
    q -= a;
    *q = '\0';

    if (!str[0])
	syslinux_run_default();
    else
	syslinux_run_command(str);
}

int main(int argc, char *argv[])
{
    char **args[2];
    int arg = 0;

    if (argc)
	arg++;
    args[0] = &argv[arg];
    args[1] = NULL;
    while (arg < argc) {
	if (!strcmp(argv[arg], "--")) {
	    argv[arg] = NULL;
	    args[1] = &argv[arg + 1];
	    break;
	}
	arg++;
    }
    if (args[1] != NULL) {
	boot_args(plop_INT13h_check()? args[0] : args[1]);
    } else {
	fprintf(stderr,
		"Usage:   ifplop.c32 [<plop_detected>] -- [<plop_not_detected>]\n"
		"Example: ifplop.c32 menu.c32 another.cfg -- plpbt hiddenusb usb1=2\n");
    }

    return 0;
}