aboutsummaryrefslogtreecommitdiffstats
path: root/core/fs/pxe/gpxeurl.c
blob: 6bbae3c2edccdb22ee82f51b08ec5ca133008530 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "pxe.h"
#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);
}

/**
 * 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 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->fill_buffer = gpxe_get_packet;
    socket->close = gpxe_close_file;
    socket->tftp_remoteport = file_open.FileHandle;
    inode->size = -1; /* This is not an error */
}

#endif /* GPXE */