private void SendMicrocodeResponse(PUP p) { // // The request PUP contains the file number in the lower-order 16-bits of the pup ID. // Assuming the number is a valid bootfile, we start sending it to the client's port via EFTP. // ushort fileNumber = (ushort)p.ID; Log.Write(LogType.Verbose, LogComponent.MiscServices, "Microcode request is for file {0}.", fileNumber); FileStream microcodeFile = BootServer.GetStreamForNumber(fileNumber); if (microcodeFile == null) { Log.Write(LogType.Warning, LogComponent.MiscServices, "Microcode file {0} does not exist or could not be opened.", fileNumber); } else { // Send the file. The MicrocodeReply protocol is extremely simple: // Just send a sequence of MicrocodeReply PUPs containing the microcode data, // there are no acks or flow control of any kind. Log.Write(LogType.Warning, LogComponent.MiscServices, "Sending microcode file {0}.", fileNumber); SendMicrocodeFile(p.SourcePort, microcodeFile); } }
private void SendBootDirectory(PUP p) { // // From etherboot.bravo // "Pup ID: if it is in reply to a BootDirRequest, the ID should match the request. // Pup Contents: 1 or more blocks of the following format: A boot file number (the number that goes in the low 16 bits of a // BootFileRequest Pup), an Alto format date (2 words), a boot file name in BCPL string format." // MemoryStream ms = new MemoryStream(PUP.MAX_PUP_SIZE); List <BootFileEntry> bootFiles = BootServer.EnumerateBootFiles(); foreach (BootFileEntry entry in bootFiles) { BootDirectoryBlock block; block.FileNumber = entry.BootNumber; block.FileDate = 0; block.FileName = new BCPLString(entry.Filename); byte[] serialized = Serializer.Serialize(block); // // If this block fits into the current PUP, add it to the stream, otherwise send off the current PUP // and start a new one. // if (serialized.Length + ms.Length <= PUP.MAX_PUP_SIZE) { ms.Write(serialized, 0, serialized.Length); } else { PUPPort localPort = new PUPPort(DirectoryServices.Instance.LocalHostAddress, p.DestinationPort.Socket); PUP bootDirReply = new PUP(PupType.BootDirectoryReply, p.ID, p.SourcePort, localPort, ms.ToArray()); Router.Instance.SendPup(bootDirReply); ms.Seek(0, SeekOrigin.Begin); ms.SetLength(0); } } // Shuffle out any remaining data. if (ms.Length > 0) { PUPPort localPort = new PUPPort(DirectoryServices.Instance.LocalHostAddress, p.DestinationPort.Socket); PUP bootDirReply = new PUP(PupType.BootDirectoryReply, p.ID, p.SourcePort, localPort, ms.ToArray()); Router.Instance.SendPup(bootDirReply); } }
private void SendBootFile(PUP p) { // // The request PUP contains the file number in the lower-order 16-bits of the pup ID. // Assuming the number is a valid bootfile, we start sending it to the client's port via EFTP. // ushort fileNumber = (ushort)p.ID; Log.Write(LogType.Verbose, LogComponent.MiscServices, "Boot file request is for file {0}.", fileNumber); FileStream bootFile = BootServer.GetStreamForNumber(fileNumber); if (bootFile == null) { Log.Write(LogType.Warning, LogComponent.MiscServices, "Boot file {0} does not exist or could not be opened.", fileNumber); } else { // Send the file. EFTPManager.SendFile(p.SourcePort, bootFile); } }