core: do aligned transfers in bcopy32
[syslinux.git] / com32 / modules / sanboot.c
blobb8bfe25e2cc99576a3e61f7b556a15e96991d3cb
1 /* ----------------------------------------------------------------------- *
3 * Copyright 2008 H. Peter Anvin - All Rights Reserved
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
8 * Boston MA 02110-1301, USA; either version 2 of the License, or
9 * (at your option) any later version; incorporated herein by reference.
11 * ----------------------------------------------------------------------- */
14 * sanboot.c
16 * Invoke the gPXE "sanboot" command, if available.
19 #include <alloca.h>
20 #include <inttypes.h>
21 #include <stdio.h>
22 #include <console.h>
23 #include <com32.h>
24 #include <stdbool.h>
25 #include <string.h>
26 #include <syslinux/config.h>
28 struct segoff16 {
29 uint16_t offs, seg;
32 struct s_PXENV_FILE_CHECK_API {
33 uint16_t Status;
34 uint16_t Size;
35 uint32_t Magic;
36 uint32_t Provider;
37 uint32_t APIMask;
38 uint32_t Flags;
41 static bool is_gpxe(void)
43 const struct syslinux_version *sv;
44 com32sys_t reg;
45 struct s_PXENV_FILE_CHECK_API *fca;
47 sv = syslinux_version();
48 if (sv->filesystem != SYSLINUX_FS_PXELINUX)
49 return false; /* Not PXELINUX */
51 fca = __com32.cs_bounce;
52 memset(fca, 0, sizeof *fca);
53 fca->Size = sizeof *fca;
54 fca->Magic = 0x91d447b2;
56 memset(&reg, 0, sizeof reg);
57 reg.eax.w[0] = 0x0009;
58 reg.ebx.w[0] = 0x00e6; /* PXENV_FILE_API_CHECK */
59 reg.edi.w[0] = OFFS(fca);
60 reg.es = SEG(fca);
62 __intcall(0x22, &reg, &reg);
64 if (reg.eflags.l & EFLAGS_CF)
65 return false; /* Cannot invoke PXE stack */
67 if (reg.eax.w[0] || fca->Status)
68 return false; /* PXE failure */
70 if (fca->Magic != 0xe9c17b20)
71 return false; /* Incorrect magic */
73 if (fca->Size < sizeof *fca)
74 return false; /* Short return */
76 if (!(fca->APIMask & (1 << 5)))
77 return false; /* No FILE EXEC */
79 return true;
82 struct s_PXENV_FILE_EXEC {
83 uint16_t Status;
84 struct segoff16 Command;
87 static void sanboot(const char **args)
89 char *q;
90 struct s_PXENV_FILE_EXEC *fx;
91 com32sys_t reg;
93 memset(&reg, 0, sizeof reg);
95 fx = __com32.cs_bounce;
96 q = (char *)(fx+1);
98 fx->Status = 1;
99 fx->Command.offs = OFFS(q);
100 fx->Command.seg = SEG(q);
102 q = stpcpy(q, "sanboot");
104 while (*args) {
105 *q++ = ' ';
106 q = stpcpy(q, *args);
107 args++;
110 memset(&reg, 0, sizeof reg);
111 reg.eax.w[0] = 0x0009;
112 reg.ebx.w[0] = 0x00e5; /* PXENV_FILE_EXEC */
113 reg.edi.w[0] = OFFS(fx);
114 reg.es = SEG(fx);
116 __intcall(0x22, &reg, &reg);
118 /* This should not return... */
121 int main(int argc, const char *argv[])
123 openconsole(&dev_null_r, &dev_stdcon_w);
125 if (argc < 2) {
126 printf("Usage: sanboot rootpath\n");
127 return 1;
130 if (!is_gpxe()) {
131 printf("sanboot: gPXE API not detected\n");
132 return 1;
135 sanboot(argv+1);
137 /* sanboot() should not return... */
138 printf("SAN boot failed.\n");
139 return 1;