ReactOS 0.4.15-dev-7788-g1ad9096
pxe.c
Go to the documentation of this file.
1/*
2 * FreeLoader
3 * Copyright (C) 2011 Hervé Poussineau
4 *
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; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include <freeldr.h>
21
22#include <debug.h>
24
25#define TAG_PXE_FILE 'FexP'
26#define NO_FILE ((ULONG)-1)
27
28static IP4 _ServerIP = { 0, };
30static CHAR _OpenFileName[128];
31static ULONG _FileSize = 0;
34static UCHAR _Packet[1024]; // Should be a value which can be transferred well in one packet over the network
36
37static PPXE
39{
40 PPXE Ptr;
41 UCHAR Checksum;
42 UCHAR i;
43
44 /* Find the '!PXE' structure */
45 Ptr = (PPXE)0xA0000;
46 while ((ULONG_PTR)Ptr > 0x10000)
47 {
48 Ptr = (PPXE)((ULONG_PTR)Ptr - 0x10);
49
50 /* Look for signature */
51 if (memcmp(Ptr, "!PXE", 4) != 0)
52 continue;
53
54 /* Check size */
55 if (Ptr->StructLength != sizeof(PXE))
56 continue;
57
58 /* Check checksum */
59 Checksum = 0;
60 for (i = 0; i < Ptr->StructLength; i++)
61 Checksum += *((PUCHAR)Ptr + i);
62 if (Checksum != 0)
63 continue;
64
65 TRACE("!PXE structure found at %p\n", Ptr);
66 return Ptr;
67 }
68
69 return NULL;
70}
71
73{
74 static PPXE pPxe = NULL;
75 static BOOLEAN bPxeSearched = FALSE;
76 if (!bPxeSearched)
77 {
78 pPxe = FindPxeStructure();
79 bPxeSearched = TRUE;
80 }
81 return pPxe;
82}
83
86{
87 PPXE pxe;
89
90 pxe = GetPxeStructure();
91 if (!pxe)
92 return FALSE;
93
95 {
96 // HACK: this delay shouldn't be necessary
97 KeStallExecutionProcessor(100 * 1000); // 100 ms
98 TRACE("PxeCall(0x%x, %p)\n", Service, Parameter);
99 }
100
103 {
104 ERR("PxeCall(0x%x, %p) failed with exit=%d status=0x%x\n",
106 return FALSE;
107 }
109 {
110 ERR("PxeCall(0x%x, %p) succeeded, but returned error status 0x%x\n",
112 return FALSE;
113 }
114 return TRUE;
115}
116
118{
119 t_PXENV_TFTP_CLOSE closeData;
120
121 if (_OpenFile == NO_FILE || FileId != _OpenFile)
122 return EBADF;
123
124 RtlZeroMemory(&closeData, sizeof(closeData));
125 if (!CallPxe(PXENV_TFTP_CLOSE, &closeData))
126 return EIO;
127
129 return ESUCCESS;
130}
131
133{
134 if (_OpenFile == NO_FILE || FileId != _OpenFile)
135 return EBADF;
136
138 Information->EndingAddress.LowPart = _FileSize;
139 Information->CurrentAddress.LowPart = _FilePosition;
140
141 TRACE("PxeGetFileInformation(%lu) -> FileSize = %lu, FilePointer = 0x%lx\n",
142 FileId, Information->EndingAddress.LowPart, Information->CurrentAddress.LowPart);
143
144 return ESUCCESS;
145}
146
147static ARC_STATUS PxeOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
148{
149 t_PXENV_TFTP_GET_FSIZE sizeData;
150 t_PXENV_TFTP_OPEN openData;
151 SIZE_T PathLen, i;
152
153 if (_OpenFile != NO_FILE)
154 return EIO;
155 if (OpenMode != OpenReadOnly)
156 return EACCES;
157
158 /* Retrieve the path length without NULL terminator */
159 PathLen = (Path ? min(strlen(Path), sizeof(_OpenFileName) - 1) : 0);
160
161 /* Lowercase the path and always use slashes as separators */
162 for (i = 0; i < PathLen; i++)
163 {
164 if (Path[i] == '\\')
165 _OpenFileName[i] = '/';
166 else
168 }
169
170 /* Zero out rest of the file name */
171 RtlZeroMemory(_OpenFileName + PathLen, sizeof(_OpenFileName) - PathLen);
172
173 RtlZeroMemory(&sizeData, sizeof(sizeData));
174 sizeData.ServerIPAddress = _ServerIP;
176 if (!CallPxe(PXENV_TFTP_GET_FSIZE, &sizeData))
177 {
178 ERR("Failed to get '%s' size\n", Path);
179 return EIO;
180 }
181
182 _FileSize = sizeData.FileSize;
183 _CachedLength = 0;
184
185 RtlZeroMemory(&openData, sizeof(openData));
186 openData.ServerIPAddress = _ServerIP;
188 openData.PacketSize = sizeof(_Packet);
189
190 if (!CallPxe(PXENV_TFTP_OPEN, &openData))
191 return ENOENT;
192
193 _FilePosition = 0;
194 _PacketPosition = 0;
195
196 _OpenFile = *FileId;
197 return ESUCCESS;
198}
199
201{
202 t_PXENV_TFTP_READ readData;
203 ULONG i;
204
205 *Count = 0;
206
207 if (_OpenFile == NO_FILE || FileId != _OpenFile)
208 return EBADF;
209
210 RtlZeroMemory(&readData, sizeof(readData));
211 readData.Buffer.segment = ((ULONG_PTR)_Packet & 0xf0000) / 16;
212 readData.Buffer.offset = (ULONG_PTR)_Packet & 0xffff;
213
214 // Get new packets as required
215 while (N > 0)
216 {
218 i = N;
219 else
222 _FilePosition += i;
223 Buffer = (UCHAR*)Buffer + i;
224 *Count += i;
225 N -= i;
226 if (N == 0)
227 break;
228
229 if (!CallPxe(PXENV_TFTP_READ, &readData))
230 return EIO;
232 _CachedLength += readData.BufferSize;
233 }
234
235 return ESUCCESS;
236}
237
239{
240 t_PXENV_TFTP_READ readData;
241
242 if (_OpenFile == NO_FILE || FileId != _OpenFile)
243 return EBADF;
244
245 if (Position->HighPart != 0 || SeekMode != SeekAbsolute)
246 return EINVAL;
247
248 if (Position->LowPart < _FilePosition)
249 {
250 // Close and reopen the file to go to position 0
251 if (PxeClose(FileId) != ESUCCESS)
252 return EIO;
253 if (PxeOpen(_OpenFileName, OpenReadOnly, &FileId) != ESUCCESS)
254 return EIO;
255 }
256
257 RtlZeroMemory(&readData, sizeof(readData));
258 readData.Buffer.segment = ((ULONG_PTR)_Packet & 0xf0000) / 16;
259 readData.Buffer.offset = (ULONG_PTR)_Packet & 0xffff;
260
261 // Get new packets as required
262 while (Position->LowPart > _CachedLength)
263 {
264 if (!CallPxe(PXENV_TFTP_READ, &readData))
265 return EIO;
267 _CachedLength += readData.BufferSize;
268 }
269
270 _FilePosition = Position->LowPart;
271 return ESUCCESS;
272}
273
274static const DEVVTBL PxeVtbl = {
275 PxeClose,
277 PxeOpen,
278 PxeRead,
279 PxeSeek,
280};
281
282const DEVVTBL* PxeMount(ULONG DeviceId)
283{
284 if (GetPxeStructure() == NULL)
285 return NULL;
286 return &PxeVtbl;
287}
288
290{
291 // Nothing to do
292 return ESUCCESS;
293}
294
296{
297 // No disk access in PXE mode
298 return EINVAL;
299}
300
301static ARC_STATUS PxeDiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
302{
303 // Nothing to do
304 return ESUCCESS;
305}
306
308{
309 // No disk access in PXE mode
310 return EINVAL;
311}
312
314{
315 // No disk access in PXE mode
316 return EINVAL;
317}
318
319static const DEVVTBL PxeDiskVtbl = {
325};
326
328{
330 BOOLEAN res;
331 UCHAR* Packet;
332
333 RtlZeroMemory(&Data, sizeof(Data));
335
337 if (!res)
338 return FALSE;
339 if (Data.BufferSize < 36)
340 return FALSE;
341 Packet = (UCHAR*)((ULONG_PTR)(Data.Buffer.segment << 4) + Data.Buffer.offset);
342 RtlCopyMemory(&_ServerIP, Packet + 20, sizeof(IP4));
343 return TRUE;
344}
345
347{
348 static BOOLEAN Initialized = FALSE;
349 static BOOLEAN Success = FALSE;
350
351 // Do initialization only once
352 if (Initialized)
353 return Success;
355
356 // Check if PXE is available
358 {
359 FsRegisterDevice("net(0)", &PxeDiskVtbl);
360 Success = TRUE;
361 }
362
363 return Success;
364}
365
#define N
Definition: crc32.c:57
unsigned short UINT16
unsigned char BOOLEAN
PRTL_UNICODE_STRING_BUFFER Path
#define ENOENT
Definition: acclib.h:79
#define EINVAL
Definition: acclib.h:90
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define EIO
Definition: acclib.h:81
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define EACCES
Definition: acclib.h:85
#define EBADF
Definition: acclib.h:82
int tolower(int c)
Definition: utclib.c:902
#define __cdecl
Definition: accygwin.h:79
UINT16 PXENV_STATUS
Definition: pxe.h:8
#define PXENV_TFTP_READ
Definition: pxe.h:589
#define PXENV_TFTP_CLOSE
Definition: pxe.h:588
#define PXENV_EXIT_SUCCESS
Definition: pxe.h:457
#define PXENV_TFTP_GET_FSIZE
Definition: pxe.h:591
struct s_PXE * PPXE
#define PXENV_PACKET_TYPE_CACHED_REPLY
Definition: pxe.h:403
UINT16 PXENV_EXIT
Definition: pxe.h:7
#define PXENV_TFTP_OPEN
Definition: pxe.h:587
#define PXENV_STATUS_SUCCESS
Definition: pxe.h:461
#define PXENV_GET_CACHED_INFO
Definition: pxe.h:597
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:81
#define ERR(fmt,...)
Definition: debug.h:110
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:103
VOID FsRegisterDevice(CHAR *Prefix, const DEVVTBL *FuncTable)
Definition: fs.c:385
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ULONG_PTR
Definition: config.h:101
@ Success
Definition: eventcreate.c:712
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
GLuint res
Definition: glext.h:9613
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define min(a, b)
Definition: monoChain.cc:55
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
@ Initialized
Definition: ketypes.h:388
int Count
Definition: noreturn.cpp:7
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
@ Service
Definition: ntsecapi.h:292
static ULONG _CachedLength
Definition: pxe.c:35
static const DEVVTBL PxeVtbl
Definition: pxe.c:274
const DEVVTBL * PxeMount(ULONG DeviceId)
Definition: pxe.c:282
static ARC_STATUS PxeDiskOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: pxe.c:301
static const DEVVTBL PxeDiskVtbl
Definition: pxe.c:319
static BOOLEAN GetCachedInfo(VOID)
Definition: pxe.c:327
static ARC_STATUS PxeOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: pxe.c:147
static ULONG _FileSize
Definition: pxe.c:31
static ARC_STATUS PxeDiskRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: pxe.c:307
static ARC_STATUS PxeRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: pxe.c:200
static ARC_STATUS PxeDiskSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: pxe.c:313
BOOLEAN CallPxe(UINT16 Service, PVOID Parameter)
Definition: pxe.c:85
static PPXE FindPxeStructure(VOID)
Definition: pxe.c:38
static ARC_STATUS PxeDiskClose(ULONG FileId)
Definition: pxe.c:289
PXENV_EXIT __cdecl PxeCallApi(UINT16 Segment, UINT16 Offset, UINT16 Service, VOID *Parameter)
BOOLEAN PxeInit(VOID)
Definition: pxe.c:346
#define NO_FILE
Definition: pxe.c:26
static ULONG _PacketPosition
Definition: pxe.c:33
static ARC_STATUS PxeGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: pxe.c:132
static ULONG _OpenFile
Definition: pxe.c:29
static ULONG _FilePosition
Definition: pxe.c:32
static CHAR _OpenFileName[128]
Definition: pxe.c:30
static ARC_STATUS PxeSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: pxe.c:238
static ARC_STATUS PxeClose(ULONG FileId)
Definition: pxe.c:117
static UCHAR _Packet[1024]
Definition: pxe.c:34
static IP4 _ServerIP
Definition: pxe.c:28
static ARC_STATUS PxeDiskGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: pxe.c:295
static PPXE GetPxeStructure(VOID)
Definition: pxe.c:72
@ ESUCCESS
Definition: arc.h:32
ULONG ARC_STATUS
Definition: arc.h:4
@ SeekAbsolute
Definition: arc.h:59
enum _OPENMODE OPENMODE
enum _SEEKMODE SEEKMODE
@ OpenReadOnly
Definition: arc.h:65
#define exit(n)
Definition: config.h:202
#define TRACE(s)
Definition: solgame.cpp:4
UINT8 FileName[128]
Definition: pxe.h:354
IP4 ServerIPAddress
Definition: pxe.h:314
UINT16 PacketSize
Definition: pxe.h:318
UINT8 FileName[128]
Definition: pxe.h:316
SEGOFF16 Buffer
Definition: pxe.h:331
UINT16 BufferSize
Definition: pxe.h:330
Definition: pxe.h:39
SEGOFF16 EntryPointSP
Definition: pxe.h:47
SEGSEL segment
Definition: pxe.h:35
OFF16 offset
Definition: pxe.h:34
Definition: fs.h:25
static COORD Position
Definition: mouse.c:34
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
Definition: pxe.h:17
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175