ReactOS 0.4.16-dev-746-g329a414
pxe.c File Reference
#include <freeldr.h>
#include <debug.h>
Include dependency graph for pxe.c:

Go to the source code of this file.

Macros

#define TAG_PXE_FILE   'FexP'
 
#define NO_FILE   ((ULONG)-1)
 

Functions

 DBG_DEFAULT_CHANNEL (FILESYSTEM)
 
static PPXE FindPxeStructure (VOID)
 
static PPXE GetPxeStructure (VOID)
 
PXENV_EXIT __cdecl PxeCallApi (UINT16 Segment, UINT16 Offset, UINT16 Service, VOID *Parameter)
 
BOOLEAN CallPxe (UINT16 Service, PVOID Parameter)
 
static ARC_STATUS PxeClose (ULONG FileId)
 
static ARC_STATUS PxeGetFileInformation (ULONG FileId, FILEINFORMATION *Information)
 
static ARC_STATUS PxeOpen (CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
 
static ARC_STATUS PxeRead (ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
 
static ARC_STATUS PxeSeek (ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
 
const DEVVTBLPxeMount (ULONG DeviceId)
 
static ARC_STATUS PxeDiskClose (ULONG FileId)
 
static ARC_STATUS PxeDiskGetFileInformation (ULONG FileId, FILEINFORMATION *Information)
 
static ARC_STATUS PxeDiskOpen (CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
 
static ARC_STATUS PxeDiskRead (ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
 
static ARC_STATUS PxeDiskSeek (ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
 
static BOOLEAN GetCachedInfo (VOID)
 
BOOLEAN PxeInit (VOID)
 

Variables

static IP4 _ServerIP = { 0, }
 
static ULONG _OpenFile = NO_FILE
 
static CHAR _OpenFileName [128]
 
static ULONG _FileSize = 0
 
static ULONG _FilePosition = 0
 
static ULONG _PacketPosition = 0
 
static UCHAR _Packet [1024]
 
static ULONG _CachedLength = 0
 
static const DEVVTBL PxeVtbl
 
static const DEVVTBL PxeDiskVtbl
 

Macro Definition Documentation

◆ NO_FILE

#define NO_FILE   ((ULONG)-1)

Definition at line 26 of file pxe.c.

◆ TAG_PXE_FILE

#define TAG_PXE_FILE   'FexP'

Definition at line 25 of file pxe.c.

Function Documentation

◆ CallPxe()

BOOLEAN CallPxe ( UINT16  Service,
PVOID  Parameter 
)

Definition at line 85 of file pxe.c.

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 StallExecutionProcessor(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}
UINT16 PXENV_STATUS
Definition: pxe.h:8
#define PXENV_TFTP_READ
Definition: pxe.h:589
#define PXENV_EXIT_SUCCESS
Definition: pxe.h:457
UINT16 PXENV_EXIT
Definition: pxe.h:7
#define PXENV_STATUS_SUCCESS
Definition: pxe.h:461
#define ERR(fmt,...)
Definition: precomp.h:57
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
@ Service
Definition: ntsecapi.h:292
VOID StallExecutionProcessor(ULONG Microseconds)
Definition: pchw.c:60
PXENV_EXIT __cdecl PxeCallApi(UINT16 Segment, UINT16 Offset, UINT16 Service, VOID *Parameter)
static PPXE GetPxeStructure(VOID)
Definition: pxe.c:72
#define exit(n)
Definition: config.h:202
#define TRACE(s)
Definition: solgame.cpp:4
Definition: pxe.h:39
SEGOFF16 EntryPointSP
Definition: pxe.h:47
SEGSEL segment
Definition: pxe.h:35
OFF16 offset
Definition: pxe.h:34
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:336

Referenced by GetCachedInfo(), PxeClose(), PxeOpen(), PxeRead(), and PxeSeek().

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( FILESYSTEM  )

◆ FindPxeStructure()

static PPXE FindPxeStructure ( VOID  )
static

Definition at line 38 of file pxe.c.

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}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
struct s_PXE * PPXE
#define NULL
Definition: types.h:112
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
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
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by GetPxeStructure().

◆ GetCachedInfo()

static BOOLEAN GetCachedInfo ( VOID  )
static

Definition at line 335 of file pxe.c.

336{
338 BOOLEAN res;
339 UCHAR* Packet;
340
341 RtlZeroMemory(&Data, sizeof(Data));
343
345 if (!res)
346 return FALSE;
347 if (Data.BufferSize < 36)
348 return FALSE;
349 Packet = (UCHAR*)((ULONG_PTR)(Data.Buffer.segment << 4) + Data.Buffer.offset);
350 RtlCopyMemory(&_ServerIP, Packet + 20, sizeof(IP4));
351 return TRUE;
352}
unsigned char BOOLEAN
#define PXENV_PACKET_TYPE_CACHED_REPLY
Definition: pxe.h:403
#define PXENV_GET_CACHED_INFO
Definition: pxe.h:597
GLuint res
Definition: glext.h:9613
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
BOOLEAN CallPxe(UINT16 Service, PVOID Parameter)
Definition: pxe.c:85
static IP4 _ServerIP
Definition: pxe.c:28
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
Definition: pxe.h:17

Referenced by PxeInit().

◆ GetPxeStructure()

static PPXE GetPxeStructure ( VOID  )
static

Definition at line 72 of file pxe.c.

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}
static PPXE FindPxeStructure(VOID)
Definition: pxe.c:38

Referenced by CallPxe(), PxeInit(), and PxeMount().

◆ PxeCallApi()

PXENV_EXIT __cdecl PxeCallApi ( UINT16  Segment,
UINT16  Offset,
UINT16  Service,
VOID Parameter 
)

Referenced by CallPxe().

◆ PxeClose()

static ARC_STATUS PxeClose ( ULONG  FileId)
static

Definition at line 117 of file pxe.c.

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}
#define EIO
Definition: acclib.h:81
#define EBADF
Definition: acclib.h:82
#define PXENV_TFTP_CLOSE
Definition: pxe.h:588
#define NO_FILE
Definition: pxe.c:26
static ULONG _OpenFile
Definition: pxe.c:29
@ ESUCCESS
Definition: arc.h:32

Referenced by PxeSeek().

◆ PxeDiskClose()

static ARC_STATUS PxeDiskClose ( ULONG  FileId)
static

Definition at line 297 of file pxe.c.

298{
299 // Nothing to do
300 return ESUCCESS;
301}

◆ PxeDiskGetFileInformation()

static ARC_STATUS PxeDiskGetFileInformation ( ULONG  FileId,
FILEINFORMATION Information 
)
static

Definition at line 303 of file pxe.c.

304{
305 // No disk access in PXE mode
306 return EINVAL;
307}
#define EINVAL
Definition: acclib.h:90

◆ PxeDiskOpen()

static ARC_STATUS PxeDiskOpen ( CHAR Path,
OPENMODE  OpenMode,
ULONG FileId 
)
static

Definition at line 309 of file pxe.c.

310{
311 // Nothing to do
312 return ESUCCESS;
313}

◆ PxeDiskRead()

static ARC_STATUS PxeDiskRead ( ULONG  FileId,
VOID Buffer,
ULONG  N,
ULONG Count 
)
static

Definition at line 315 of file pxe.c.

316{
317 // No disk access in PXE mode
318 return EINVAL;
319}

◆ PxeDiskSeek()

static ARC_STATUS PxeDiskSeek ( ULONG  FileId,
LARGE_INTEGER Position,
SEEKMODE  SeekMode 
)
static

Definition at line 321 of file pxe.c.

322{
323 // No disk access in PXE mode
324 return EINVAL;
325}

◆ PxeGetFileInformation()

static ARC_STATUS PxeGetFileInformation ( ULONG  FileId,
FILEINFORMATION Information 
)
static

Definition at line 132 of file pxe.c.

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}
static ULONG _FileSize
Definition: pxe.c:31
static ULONG _FilePosition
Definition: pxe.c:32
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049

◆ PxeInit()

BOOLEAN PxeInit ( VOID  )

Definition at line 354 of file pxe.c.

355{
356 static BOOLEAN Initialized = FALSE;
357 static BOOLEAN Success = FALSE;
358
359 // Do initialization only once
360 if (Initialized)
361 return Success;
363
364 // Check if PXE is available
366 {
367 FsRegisterDevice("net(0)", &PxeDiskVtbl);
368 Success = TRUE;
369 }
370
371 return Success;
372}
VOID FsRegisterDevice(_In_ PCSTR DeviceName, _In_ const DEVVTBL *FuncTable)
Definition: fs.c:596
@ Success
Definition: eventcreate.c:712
@ Initialized
Definition: ketypes.h:388
static const DEVVTBL PxeDiskVtbl
Definition: pxe.c:327
static BOOLEAN GetCachedInfo(VOID)
Definition: pxe.c:335

Referenced by PcInitializeBootDevices().

◆ PxeMount()

const DEVVTBL * PxeMount ( ULONG  DeviceId)

Definition at line 290 of file pxe.c.

291{
292 if (GetPxeStructure() == NULL)
293 return NULL;
294 return &PxeVtbl;
295}
static const DEVVTBL PxeVtbl
Definition: pxe.c:282

◆ PxeOpen()

static ARC_STATUS PxeOpen ( CHAR Path,
OPENMODE  OpenMode,
ULONG FileId 
)
static

Definition at line 147 of file pxe.c.

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 /* Skip leading path separator, if any, so as to ensure that
159 * we always lookup the file at the root of the TFTP server's
160 * file space ("virtual root"), even if the server doesn't
161 * support this, and NOT from the root of the file system. */
162 if (*Path == '\\' || *Path == '/')
163 ++Path;
164
165 /* Retrieve the path length without NULL terminator */
166 PathLen = min(strlen(Path), sizeof(_OpenFileName) - 1);
167
168 /* Lowercase the path and always use slashes as separators,
169 * for supporting TFTP servers on POSIX systems */
170 for (i = 0; i < PathLen; i++)
171 {
172 if (Path[i] == '\\')
173 _OpenFileName[i] = '/';
174 else
176 }
177
178 /* Zero out rest of the file name */
179 RtlZeroMemory(_OpenFileName + PathLen, sizeof(_OpenFileName) - PathLen);
180
181 RtlZeroMemory(&sizeData, sizeof(sizeData));
182 sizeData.ServerIPAddress = _ServerIP;
184 if (!CallPxe(PXENV_TFTP_GET_FSIZE, &sizeData))
185 {
186 ERR("Failed to get '%s' size\n", Path);
187 return EIO;
188 }
189
190 _FileSize = sizeData.FileSize;
191 _CachedLength = 0;
192
193 RtlZeroMemory(&openData, sizeof(openData));
194 openData.ServerIPAddress = _ServerIP;
196 openData.PacketSize = sizeof(_Packet);
197
198 if (!CallPxe(PXENV_TFTP_OPEN, &openData))
199 return ENOENT;
200
201 _FilePosition = 0;
202 _PacketPosition = 0;
203
204 _OpenFile = *FileId;
205 return ESUCCESS;
206}
PRTL_UNICODE_STRING_BUFFER Path
#define ENOENT
Definition: acclib.h:79
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define EACCES
Definition: acclib.h:85
int tolower(int c)
Definition: utclib.c:902
#define PXENV_TFTP_GET_FSIZE
Definition: pxe.h:591
#define PXENV_TFTP_OPEN
Definition: pxe.h:587
#define min(a, b)
Definition: monoChain.cc:55
static ULONG _CachedLength
Definition: pxe.c:35
static ULONG _PacketPosition
Definition: pxe.c:33
static CHAR _OpenFileName[128]
Definition: pxe.c:30
static UCHAR _Packet[1024]
Definition: pxe.c:34
@ OpenReadOnly
Definition: arc.h:65
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
ULONG_PTR SIZE_T
Definition: typedefs.h:80

Referenced by PxeSeek().

◆ PxeRead()

static ARC_STATUS PxeRead ( ULONG  FileId,
VOID Buffer,
ULONG  N,
ULONG Count 
)
static

Definition at line 208 of file pxe.c.

209{
210 t_PXENV_TFTP_READ readData;
211 ULONG i;
212
213 *Count = 0;
214
215 if (_OpenFile == NO_FILE || FileId != _OpenFile)
216 return EBADF;
217
218 RtlZeroMemory(&readData, sizeof(readData));
219 readData.Buffer.segment = ((ULONG_PTR)_Packet & 0xf0000) / 16;
220 readData.Buffer.offset = (ULONG_PTR)_Packet & 0xffff;
221
222 // Get new packets as required
223 while (N > 0)
224 {
226 i = N;
227 else
230 _FilePosition += i;
231 Buffer = (UCHAR*)Buffer + i;
232 *Count += i;
233 N -= i;
234 if (N == 0)
235 break;
236
237 if (!CallPxe(PXENV_TFTP_READ, &readData))
238 return EIO;
240 _CachedLength += readData.BufferSize;
241 }
242
243 return ESUCCESS;
244}
#define N
Definition: crc32.c:57
Definition: bufpool.h:45
#define ULONG_PTR
Definition: config.h:101
int Count
Definition: noreturn.cpp:7
SEGOFF16 Buffer
Definition: pxe.h:331
UINT16 BufferSize
Definition: pxe.h:330
uint32_t ULONG
Definition: typedefs.h:59

◆ PxeSeek()

static ARC_STATUS PxeSeek ( ULONG  FileId,
LARGE_INTEGER Position,
SEEKMODE  SeekMode 
)
static

Definition at line 246 of file pxe.c.

247{
248 t_PXENV_TFTP_READ readData;
249
250 if (_OpenFile == NO_FILE || FileId != _OpenFile)
251 return EBADF;
252
253 if (Position->HighPart != 0 || SeekMode != SeekAbsolute)
254 return EINVAL;
255
256 if (Position->LowPart < _FilePosition)
257 {
258 // Close and reopen the file to go to position 0
259 if (PxeClose(FileId) != ESUCCESS)
260 return EIO;
261 if (PxeOpen(_OpenFileName, OpenReadOnly, &FileId) != ESUCCESS)
262 return EIO;
263 }
264
265 RtlZeroMemory(&readData, sizeof(readData));
266 readData.Buffer.segment = ((ULONG_PTR)_Packet & 0xf0000) / 16;
267 readData.Buffer.offset = (ULONG_PTR)_Packet & 0xffff;
268
269 // Get new packets as required
270 while (Position->LowPart > _CachedLength)
271 {
272 if (!CallPxe(PXENV_TFTP_READ, &readData))
273 return EIO;
275 _CachedLength += readData.BufferSize;
276 }
277
278 _FilePosition = Position->LowPart;
279 return ESUCCESS;
280}
static ARC_STATUS PxeOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: pxe.c:147
static ARC_STATUS PxeClose(ULONG FileId)
Definition: pxe.c:117
@ SeekAbsolute
Definition: arc.h:59
static COORD Position
Definition: mouse.c:34

Variable Documentation

◆ _CachedLength

ULONG _CachedLength = 0
static

Definition at line 35 of file pxe.c.

Referenced by PxeOpen(), PxeRead(), and PxeSeek().

◆ _FilePosition

ULONG _FilePosition = 0
static

Definition at line 32 of file pxe.c.

Referenced by PxeGetFileInformation(), PxeOpen(), PxeRead(), and PxeSeek().

◆ _FileSize

ULONG _FileSize = 0
static

Definition at line 31 of file pxe.c.

Referenced by PxeGetFileInformation(), and PxeOpen().

◆ _OpenFile

ULONG _OpenFile = NO_FILE
static

Definition at line 29 of file pxe.c.

Referenced by PxeClose(), PxeGetFileInformation(), PxeOpen(), PxeRead(), and PxeSeek().

◆ _OpenFileName

CHAR _OpenFileName[128]
static

Definition at line 30 of file pxe.c.

Referenced by PxeOpen(), and PxeSeek().

◆ _Packet

UCHAR _Packet[1024]
static

◆ _PacketPosition

ULONG _PacketPosition = 0
static

Definition at line 33 of file pxe.c.

Referenced by PxeOpen(), PxeRead(), and PxeSeek().

◆ _ServerIP

IP4 _ServerIP = { 0, }
static

Definition at line 28 of file pxe.c.

Referenced by GetCachedInfo(), and PxeOpen().

◆ PxeDiskVtbl

const DEVVTBL PxeDiskVtbl
static
Initial value:
= {
}
static ARC_STATUS PxeDiskOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: pxe.c:309
static ARC_STATUS PxeDiskRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: pxe.c:315
static ARC_STATUS PxeDiskSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: pxe.c:321
static ARC_STATUS PxeDiskClose(ULONG FileId)
Definition: pxe.c:297
static ARC_STATUS PxeDiskGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: pxe.c:303

Definition at line 327 of file pxe.c.

Referenced by PxeInit().

◆ PxeVtbl

const DEVVTBL PxeVtbl
static
Initial value:
= {
}
static ARC_STATUS PxeRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: pxe.c:208
static ARC_STATUS PxeGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: pxe.c:132
static ARC_STATUS PxeSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: pxe.c:246

Definition at line 282 of file pxe.c.

Referenced by PxeMount().