#include "libsaio.h" #include "pxe.h" #include "sl.h" /*========================================================================== * GetDirEntry is not supported. */ static long PXEGetDirEntry(CICell ih, char * dirPath, long * dirIndex, char ** name, long * flags, long * time, FinderInfo * finderInfo, long * infoValid) { return -1; } //========================================================================== static void PXEGetDescription(CICell ih, char * str, long strMaxLen) { sprintf( str, "Raw PXE Client" ); } //========================================================================== static long PXELoadFile(CICell ih, char * filePath) { if(gBootReply == NULL) return -1; // Strip leading /.. everything is relative to base dir.. no exceptions for now. while(filePath[0] == '/') ++filePath; int baselen = strlen(gPXE_BaseFilename); if(baselen + strlen(filePath) >= 127) return -1; t_PXENV_TFTP_OPEN tftpOpenCommand; bzero(&tftpOpenCommand, sizeof(tftpOpenCommand)); tftpOpenCommand.ServerIPAddress = gBootReply->sip; sprintf(tftpOpenCommand.FileName, "%s%s", gPXE_BaseFilename, filePath); tftpOpenCommand.TFTPPort = 69 << 8; // big endian tftpOpenCommand.PacketSize = 1440; uint16_t pxenv_exit; pxenv_exit = pxeCall(PXENV_TFTP_OPEN, &tftpOpenCommand); if(pxenv_exit != PXENV_EXIT_SUCCESS) { printf("TFTP Open call failed with exit %d\n", pxenv_exit); sleep(4); return -1; } if(tftpOpenCommand.Status != PXENV_STATUS_SUCCESS) { printf("TFTP Open failed with status %d\n", tftpOpenCommand.Status); sleep(4); return -1; } printf("Attempting to download \"%s\", packet size %d\n", tftpOpenCommand.FileName, tftpOpenCommand.PacketSize); t_PXENV_TFTP_READ tftpReadCommand; bzero(&tftpReadCommand, sizeof(tftpReadCommand)); char *Buffer = (void*)gFSLoadAddress; tftpReadCommand.BufferSize = tftpOpenCommand.PacketSize; while(tftpReadCommand.BufferSize >= tftpOpenCommand.PacketSize) { tftpReadCommand.Buffer.segment = 0; tftpReadCommand.Buffer.offset = BIOS_ADDR; // BufferSize is set to the amount read each time through. pxenv_exit = pxeCall(PXENV_TFTP_READ, &tftpReadCommand); if(pxenv_exit != PXENV_EXIT_SUCCESS) { printf("TFTP Read call failed with exit %d\n", pxenv_exit); sleep(4); return -1; } if(tftpReadCommand.Status != PXENV_STATUS_SUCCESS) { printf("TFTP Read failed with status %d\n", tftpOpenCommand.Status); sleep(4); return -1; } memcpy(Buffer, (void*)BIOS_ADDR, tftpReadCommand.BufferSize); Buffer += tftpReadCommand.BufferSize; } tftpOpenCommand.Status = 0; pxenv_exit = pxeCall(PXENV_TFTP_CLOSE, &tftpOpenCommand); if(pxenv_exit != PXENV_EXIT_SUCCESS) { printf("TFTP Close failed with exit %d\n", pxenv_exit); return -1; } if(tftpOpenCommand.Status != PXENV_STATUS_SUCCESS) { printf("TFTP Close failed with status %d\n", tftpOpenCommand.Status); return -1; } return (uint32_t)Buffer - (uint32_t)gFSLoadAddress; } BVRef pxeScanBootVolumes( int biosdev, int * countPtr ) { static BVRef gPxeBVR = NULL; if ( countPtr ) *countPtr = 1; // Check to see if we've already fully initialized if ( !gPxeBVR ) { if(PXEStartup()) gPxeBVR = malloc( sizeof(*gPxeBVR) ); if ( gPxeBVR ) { bzero(gPxeBVR, sizeof(*gPxeBVR)); gPxeBVR->biosdev = kNetworkDeviceType; gPxeBVR->type = kNetworkDeviceType; gPxeBVR->flags = kBVFlagPrimary | kBVFlagNativeBoot; gPxeBVR->description = PXEGetDescription; gPxeBVR->fs_loadfile = PXELoadFile; gPxeBVR->fs_getdirentry = PXEGetDirEntry; } } return biosdev==kNetworkDeviceType?gPxeBVR:NULL; }