diff options
Diffstat (limited to 'core/legacynet/core.c')
-rw-r--r-- | core/legacynet/core.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/core/legacynet/core.c b/core/legacynet/core.c index eacb4927..24a670e0 100644 --- a/core/legacynet/core.c +++ b/core/legacynet/core.c @@ -220,3 +220,104 @@ int reset_pxe(void) return err; } + +#if GPXE + +static void gpxe_close_file(struct inode *inode) +{ + struct pxe_pvt_inode *socket = PVT(inode); + static __lowmem struct s_PXENV_FILE_CLOSE file_close; + + file_close.FileHandle = socket->tftp_remoteport; + pxe_call(PXENV_FILE_CLOSE, &file_close); +} + +/** + * Get a fresh packet from a gPXE socket + * @param: inode -> Inode pointer + * + */ +static void gpxe_get_packet(struct inode *inode) +{ + struct pxe_pvt_inode *socket = PVT(inode); + static __lowmem struct s_PXENV_FILE_READ file_read; + int err; + + while (1) { + file_read.FileHandle = socket->tftp_remoteport; + file_read.Buffer = FAR_PTR(packet_buf); + file_read.BufferSize = PKTBUF_SIZE; + err = pxe_call(PXENV_FILE_READ, &file_read); + if (!err) /* successed */ + break; + + if (file_read.Status != PXENV_STATUS_TFTP_OPEN) + kaboom(); + } + + memcpy(socket->tftp_pktbuf, packet_buf, file_read.BufferSize); + + socket->tftp_dataptr = socket->tftp_pktbuf; + socket->tftp_bytesleft = file_read.BufferSize; + socket->tftp_filepos += file_read.BufferSize; + + if (socket->tftp_bytesleft == 0) + inode->size = socket->tftp_filepos; + + /* if we're done here, close the file */ + if (inode->size > socket->tftp_filepos) + return; + + /* Got EOF, close it */ + socket->tftp_goteof = 1; + gpxe_close_file(inode); +} + +const struct pxe_conn_ops gpxe_conn_ops = { + .fill_buffer = gpxe_get_packet, + .close = gpxe_close_file, +}; + +/** + * Open a url using gpxe + * + * @param:inode, the inode to store our state in + * @param:url, the url we want to open + * + * @out: open_file_t structure, stores in file->open_file + * @out: the lenght of this file, stores in file->file_len + * + */ +void gpxe_open(struct inode *inode, const char *url) +{ + static __lowmem struct s_PXENV_FILE_OPEN file_open; + static __lowmem struct s_PXENV_GET_FILE_SIZE file_size; + static __lowmem char lowurl[2*FILENAME_MAX]; + struct pxe_pvt_inode *socket = PVT(inode); + int err; + + socket->tftp_pktbuf = malloc(PKTBUF_SIZE); + if (!socket->tftp_pktbuf) + return; + + snprintf(lowurl, sizeof lowurl, "%s", url); + file_open.Status = PXENV_STATUS_BAD_FUNC; + file_open.FileName = FAR_PTR(lowurl); + err = pxe_call(PXENV_FILE_OPEN, &file_open); + if (err) + return; + + + socket->ops = &gpxe_conn_ops; + socket->tftp_remoteport = file_open.FileHandle; + file_size.Status = PXENV_STATUS_BAD_FUNC; + file_size.FileHandle = file_open.FileHandle; + err = pxe_call(PXENV_GET_FILE_SIZE, &file_size); + if (err) { + inode->size = -1; /* fallback size; this shouldn't be an error */ + } else { + inode->size = file_size.FileSize; + } +} + +#endif /* GPXE */ |