/*      $NetBSD: pxe.h,v 1.9 2025/07/09 21:25:35 andvar Exp $   */

/*
* Copyright (c) 2000 Alfred Perlstein <[email protected]>
* All rights reserved.
* Copyright (c) 2000 Paul Saab <[email protected]>
* All rights reserved.
* Copyright (c) 2000 John Baldwin <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

/*
* Note that these structures and types are named according to
* the Intel PXE documentation.
*/

#define MEMSTRCMP(p, s) memcmp((p), (s), sizeof(s) - 1)

#define IP_STR          "%d.%d.%d.%d"
#define IP_ARGS(ip)                                     \
       (int)(ip >> 24) & 0xff, (int)(ip >> 16) & 0xff, \
       (int)(ip >> 8) & 0xff, (int)ip & 0xff

#define MAC_STR         "%02x:%02x:%02x:%02x:%02x:%02x"
#define MAC_ARGS(mac)                                   \
       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]

typedef struct {
       uint16_t                offset;
       uint16_t                segment;
} __packed SEGOFF16_t;

typedef struct {
       uint16_t                Seg_Addr;
       uint32_t                Phy_Addr;
       uint16_t                Seg_Size;
} __packed SEGDESC_t;

typedef uint16_t                SEGSEL_t;
typedef uint16_t                PXENV_STATUS_t;
typedef uint32_t                IP4_t;
typedef uint32_t                ADDR32_t;
typedef uint16_t                UDP_PORT_t;

#define MAC_ADDR_LEN            16
typedef uint8_t                 MAC_ADDR[MAC_ADDR_LEN];

/* PXENV+ */
typedef struct {
       uint8_t         Signature[6];   /* 'PXENV+' */
       uint16_t        Version;        /* MSB = major, LSB = minor */
       uint8_t         Length;         /* structure length */
       uint8_t         Checksum;       /* checksum pad */
       SEGOFF16_t      RMEntry;        /* SEG:OFF to PXE entry point */
       /* don't use PMOffset and PMSelector (from the 2.1 PXE manual) */
       uint32_t        PMOffset;       /* Protected mode entry */
       SEGSEL_t        PMSelector;     /* Protected mode selector */
       SEGSEL_t        StackSeg;       /* Stack segment address */
       uint16_t        StackSize;      /* Stack segment size (bytes) */
       SEGSEL_t        BC_CodeSeg;     /* BC Code segment address */
       uint16_t        BC_CodeSize;    /* BC Code segment size (bytes) */
       SEGSEL_t        BC_DataSeg;     /* BC Data segment address */
       uint16_t        BC_DataSize;    /* BC Data segment size (bytes) */
       SEGSEL_t        UNDIDataSeg;    /* UNDI Data segment address */
       uint16_t        UNDIDataSize;   /* UNDI Data segment size (bytes) */
       SEGSEL_t        UNDICodeSeg;    /* UNDI Code segment address */
       uint16_t        UNDICodeSize;   /* UNDI Code segment size (bytes) */
       SEGOFF16_t      PXEPtr;         /* SEG:OFF to !PXE struct,
                                          only present when Version > 2.1 */
} __packed pxenv_t;

/* !PXE */
typedef struct {
       uint8_t         Signature[4];
       uint8_t         StructLength;
       uint8_t         StructCksum;
       uint8_t         StructRev;
       uint8_t         reserved_1;
       SEGOFF16_t      UNDIROMID;
       SEGOFF16_t      BaseROMID;
       SEGOFF16_t      EntryPointSP;
       SEGOFF16_t      EntryPointESP;
       SEGOFF16_t      StatusCallout;
       uint8_t         reserved_2;
       uint8_t         SegDescCn;
       SEGSEL_t        FirstSelector;
       SEGDESC_t       Stack;
       SEGDESC_t       UNDIData;
       SEGDESC_t       UNDICode;
       SEGDESC_t       UNDICodeWrite;
       SEGDESC_t       BC_Data;
       SEGDESC_t       BC_Code;
       SEGDESC_t       BC_CodeWrite;
} __packed pxe_t;

#define PXENV_START_UNDI                0x0000
typedef struct {
       PXENV_STATUS_t  Status;
       uint16_t        ax;
       uint16_t        bx;
       uint16_t        dx;
       uint16_t        di;
       uint16_t        es;
} __packed t_PXENV_START_UNDI;

#define PXENV_UNDI_STARTUP              0x0001
typedef struct {
       PXENV_STATUS_t  Status;
} __packed t_PXENV_UNDI_STARTUP;

#define PXENV_UNDI_CLEANUP              0x0002
typedef struct {
       PXENV_STATUS_t  Status;
} __packed t_PXENV_UNDI_CLEANUP;

#define PXENV_UNDI_INITIALIZE           0x0003
typedef struct {
       PXENV_STATUS_t  Status;
       ADDR32_t        ProtocolIni;    /* Phys addr of a copy of the
                                          driver module */
       uint8_t         reserved[8];
} __packed t_PXENV_UNDI_INITIALIZE;


#define MAXNUM_MCADDR           8
typedef struct {
       PXENV_STATUS_t  Status;
       uint16_t        MCastAddrCount;
       MAC_ADDR        McastAddr[MAXNUM_MCADDR];
} __packed t_PXENV_UNDI_MCAST_ADDRESS;

#define PXENV_UNDI_RESET_ADAPTER        0x0004
typedef struct {
       PXENV_STATUS_t  Status;
       t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
} __packed t_PXENV_UNDI_RESET;

#define PXENV_UNDI_SHUTDOWN             0x0005
typedef struct {
       PXENV_STATUS_t  Status;
} __packed t_PXENV_UNDI_SHUTDOWN;

#define PXENV_UNDI_OPEN                 0x0006
typedef struct {
       PXENV_STATUS_t  Status;
       uint16_t        OpenFlag;
       uint16_t        PktFilter;
#       define FLTR_DIRECTED    0x0001
#       define FLTR_BRDCST      0x0002
#       define FLTR_PRMSCS      0x0003
#       define FLTR_SRC_RTG     0x0004

       t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
} __packed t_PXENV_UNDI_OPEN;

#define PXENV_UNDI_CLOSE                0x0007
typedef struct {
       PXENV_STATUS_t  Status;
} __packed t_PXENV_UNDI_CLOSE;

#define PXENV_UNDI_TRANSMIT             0x0008
typedef struct {
       PXENV_STATUS_t  Status;
       uint8_t         Protocol;
#       define P_UNKNOWN        0
#       define P_IP             1
#       define P_ARP            2
#       define P_RARP           3

       uint8_t         XmitFlag;
#       define XMT_DESTADDR     0x0000
#       define XMT_BROADCAST    0x0001

       SEGOFF16_t      DestAddr;
       SEGOFF16_t      TBD;
       uint32_t        Reserved[2];
} __packed t_PXENV_UNDI_TRANSMIT;

#define MAX_DATA_BLKS           8
typedef struct {
       uint16_t        ImmedLength;
       SEGOFF16_t      Xmit;
       uint16_t        DataBlkCount;
       struct  DataBlk {
               uint8_t         TDPtrType;
               uint8_t         TDRsvdByte;
               uint16_t        TDDataLen;
               SEGOFF16_t      TDDataPtr;
       } DataBlock[MAX_DATA_BLKS];
} __packed t_PXENV_UNDI_TBD;

#define PXENV_UNDI_SET_MCAST_ADDRESS    0x0009
typedef struct {
       PXENV_STATUS_t  Status;
       t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
} __packed t_PXENV_UNDI_SET_MCAST_ADDR;

#define PXENV_UNDI_SET_STATION_ADDRESS  0x000A
typedef struct {
       PXENV_STATUS_t  Status;
       MAC_ADDR        StationAddress;         /* Temp MAC address to use */
} __packed t_PXENV_UNDI_SET_STATION_ADDR;

#define PXENV_UNDI_SET_PACKET_FILTER    0x000B
typedef struct {
       PXENV_STATUS_t  Status;
       uint8_t         filter;                 /* see UNDI_OPEN (0x0006) */
} __packed t_PXENV_UNDI_SET_PACKET_FILTER;

#define PXENV_UNDI_GET_INFORMATION      0x000C
typedef struct {
       PXENV_STATUS_t  Status;
       uint16_t        BaseIo;                 /* Adapter base I/O address */
       uint16_t        IntNumber;              /* Adapter IRQ number */
       uint16_t        MaxTranUnit;            /* Adapter maximum transmit
                                                  unit */
       uint16_t        HwType;                 /* Type of protocol at the
                                                  hardware addr */
#       define ETHER_TYPE       1
#       define EXP_ETHER_TYPE   2
#       define IEEE_TYPE        6
#       define ARCNET_TYPE      7

       uint16_t        HwAddrLen;              /* Length of hardware address */
       MAC_ADDR        CurrentNodeAddress;     /* Current hardware address */
       MAC_ADDR        PermNodeAddress;        /* Permanent hardware address */
       SEGSEL_t        ROMAddress;             /* Real mode ROM segment
                                                  address */
       uint16_t        RxBufCt;                /* Receive queue length */
       uint16_t        TxBufCt;                /* Transmit queue length */
} __packed t_PXENV_UNDI_GET_INFORMATION;

#define PXENV_UNDI_GET_STATISTICS       0x000D
typedef struct {
       PXENV_STATUS_t  Status;
       uint32_t        XmitGoodFrames;         /* Number of successful
                                                  transmissions */
       uint32_t        RcvGoodFrames;          /* Number of good frames
                                                  received */
       uint32_t        RcvCRCErrors;           /* Number of frames with
                                                  CRC errors */
       uint32_t        RcvResourceErrors;      /* Number of frames dropped */
} __packed t_PXENV_UNDI_GET_STATISTICS;

#define PXENV_UNDI_CLEAR_STATISTICS     0x000E
typedef struct {
       PXENV_STATUS_t  Status;
} __packed t_PXENV_UNDI_CLEAR_STATISTICS;

#define PXENV_UNDI_INITIATE_DIAGS       0x000F
typedef struct {
       PXENV_STATUS_t  Status;
} __packed t_PXENV_UNDI_INITIATE_DIAGS;

#define PXENV_UNDI_FORCE_INTERRUPT      0x0010
typedef struct {
       PXENV_STATUS_t  Status;
} __packed t_PXENV_UNDI_FORCE_INTERRUPT;

#define PXENV_UNDI_GET_MCAST_ADDRESS    0x0011
typedef struct {
       PXENV_STATUS_t  Status;
       IP4_t           InetAddr;               /* IP multicast address */
       MAC_ADDR        MediaAddr;              /* MAC multicast address */
} __packed t_PXENV_UNDI_GET_MCAST_ADDR;

#define PXENV_UNDI_GET_NIC_TYPE         0x0012
typedef struct {
       PXENV_STATUS_t  Status;
       uint8_t         NicType;                /* Type of NIC */
#       define PCI_NIC          2
#       define PnP_NIC          3
#       define CardBus_NIC      4

       union {
               struct {
                       uint16_t        Vendor_ID;
                       uint16_t        Dev_ID;
                       uint8_t         Base_Class;
                       uint8_t         Sub_Class;
                       uint8_t         Prog_Intf;
                       uint8_t         Rev;
                       uint16_t        BusDevFunc;
                       uint16_t        SubVendor_ID;
                       uint16_t        SubDevice_ID;
               } pci, cardbus;
               struct {
                       uint32_t        EISA_Dev_ID;
                       uint8_t         Base_Class;
                       uint8_t         Sub_Class;
                       uint8_t         Prog_Intf;
                       uint16_t        CardSelNum;
               } pnp;
       } info;
} __packed t_PXENV_UNDI_GET_NIC_TYPE;

#define PXENV_UNDI_GET_IFACE_INFO       0x0013
typedef struct {
       PXENV_STATUS_t  Status;
       uint8_t         IfaceType[16];          /* Name of MAC type in ASCII. */
       uint32_t        LinkSpeed;              /* Defined in NDIS 2.0 spec */
       uint32_t        ServiceFlags;           /* Defined in NDIS 2.0 spec */
       uint32_t        Reserved[4];            /* must be 0 */
} __packed t_PXENV_UNDI_GET_NDIS_INFO;

#define PXENV_UNDI_ISR                  0x0014
typedef struct {
       PXENV_STATUS_t  Status;
       uint16_t        FuncFlag;               /* PXENV_UNDI_ISR_OUT_xxx */
       uint16_t        BufferLength;           /* Length of Frame */
       uint16_t        FrameLength;            /* Total length of receiver
                                                  frame */
       uint16_t        FrameHeaderLength;      /* Length of the media header
                                                  in Frame */
       SEGOFF16_t      Frame;                  /* receive buffer */
       uint8_t         ProtType;               /* Protocol type */
       uint8_t         PktType;                /* Packet Type */
#       define PXENV_UNDI_ISR_IN_START          1
#       define PXENV_UNDI_ISR_IN_PROCESS        2
#       define PXENV_UNDI_ISR_IN_GET_NEXT       3

       /* one of these will be returned for PXENV_UNDI_ISR_IN_START */
#       define PXENV_UNDI_ISR_OUT_OURS          0
#       define PXENV_UNDI_ISR_OUT_NOT_OUTS      1

       /*
        * one of these will be returned for PXEND_UNDI_ISR_IN_PROCESS
        * and PXENV_UNDI_ISR_IN_GET_NEXT
        */
#       define PXENV_UNDI_ISR_OUT_DONE          0
#       define PXENV_UNDI_ISR_OUT_TRANSMIT      2
#       define PXENV_UNDI_ISR_OUT_RECEIVE       3
#       define PXENV_UNDI_ISR_OUT_BUSY          4
} __packed t_PXENV_UNDI_ISR;

#define PXENV_STOP_UNDI                 0x0015
typedef struct {
       PXENV_STATUS_t  Status;
} __packed t_PXENV_STOP_UNDI;

#define PXENV_TFTP_OPEN                 0x0020
typedef struct {
       PXENV_STATUS_t  Status;
       IP4_t           ServerIPAddress;
       IP4_t           GatewayIPAddress;
       uint8_t         FileName[128];
       UDP_PORT_t      TFTPPort;
       uint16_t        PacketSize;
} __packed t_PXENV_TFTP_OPEN;

#define PXENV_TFTP_CLOSE                0x0021
typedef struct {
       PXENV_STATUS_t  Status;
} __packed t_PXENV_TFTP_CLOSE;

#define PXENV_TFTP_READ                 0x0022
typedef struct {
       PXENV_STATUS_t  Status;
       uint16_t        PacketNumber;
       uint16_t        BufferSize;
       SEGOFF16_t      Buffer;
} __packed t_PXENV_TFTP_READ;

#define PXENV_TFTP_READ_FILE            0x0023
typedef struct {
       PXENV_STATUS_t  Status;
       uint8_t         FileName[128];
       uint32_t        BufferSize;
       ADDR32_t        Buffer;
       IP4_t           ServerIPAddress;
       IP4_t           GatewayIPAddress;
       IP4_t           McastIPAddress;
       UDP_PORT_t      TFTPClntPort;
       UDP_PORT_t      TFTPSrvPort;
       uint16_t        TFTPOpenTimeOut;
       uint16_t        TFTPReopenDelay;
} __packed t_PXENV_TFTP_READ_FILE;

#define PXENV_TFTP_GET_FSIZE            0x0025
typedef struct {
       PXENV_STATUS_t  Status;
       IP4_t           ServerIPAddress;
       IP4_t           GatewayIPAddress;
       uint8_t         FileName[128];
       uint32_t        FileSize;
} __packed t_PXENV_TFTP_GET_FSIZE;

#define PXENV_UDP_OPEN                  0x0030
typedef struct {
       PXENV_STATUS_t  status;
       IP4_t           src_ip;         /* IP address of this station */
} __packed t_PXENV_UDP_OPEN;

#define PXENV_UDP_CLOSE                 0x0031
typedef struct {
       PXENV_STATUS_t  status;
} __packed t_PXENV_UDP_CLOSE;

#define PXENV_UDP_READ                  0x0032
typedef struct {
       PXENV_STATUS_t  status;
       IP4_t           src_ip;         /* IP of sender */
       IP4_t           dest_ip;        /* Only accept packets sent to
                                          this IP */
       UDP_PORT_t      s_port;         /* UDP source port of sender */
       UDP_PORT_t      d_port;         /* Only accept packets sent to
                                          this port */
       uint16_t        buffer_size;    /* Size of the packet buffer */
       SEGOFF16_t      buffer;         /* SEG:OFF to the packet buffer */
} __packed t_PXENV_UDP_READ;

#define PXENV_UDP_WRITE                 0x0033
typedef struct {
       PXENV_STATUS_t  status;
       IP4_t           ip;             /* dest ip addr */
       IP4_t           gw;             /* ip gateway */
       UDP_PORT_t      src_port;       /* source udp port */
       UDP_PORT_t      dst_port;       /* destination udp port */
       uint16_t        buffer_size;    /* Size of the packet buffer */
       SEGOFF16_t      buffer;         /* SEG:OFF to the packet buffer */
} __packed t_PXENV_UDP_WRITE;

#define PXENV_UNLOAD_STACK              0x0070
typedef struct {
       PXENV_STATUS_t  Status;
       uint8_t         reserved[10];
} __packed t_PXENV_UNLOAD_STACK;


#define PXENV_GET_CACHED_INFO           0x0071
typedef struct {
       PXENV_STATUS_t  Status;
       uint16_t        PacketType;     /* type (defined right here) */
#       define PXENV_PACKET_TYPE_DHCP_DISCOVER  1
#       define PXENV_PACKET_TYPE_DHCP_ACK       2
#       define PXENV_PACKET_TYPE_BINL_REPLY     3
       uint16_t        BufferSize;     /* max to copy, leave at 0 for
                                          pointer */
       SEGOFF16_t      Buffer;         /* copy to, leave at 0 for pointer */
       uint16_t        BufferLimit;    /* max size of buffer in BC dataseg ? */
} __packed t_PXENV_GET_CACHED_INFO;


/* structure filled in by PXENV_GET_CACHED_INFO
* (how we determine which IP we downloaded the initial bootstrap from)
* words can't describe...
*/
typedef struct {
       uint8_t         opcode;
#       define BOOTP_REQ        1
#       define BOOTP_REP        2
       uint8_t         Hardware;       /* hardware type */
       uint8_t         Hardlen;        /* hardware addr len */
       uint8_t         Gatehops;       /* zero it */
       uint32_t        ident;          /* random number chosen by client */
       uint16_t        seconds;        /* seconds since did initial
                                          bootstrap */
       uint16_t        Flags;          /* seconds since did initial
                                          bootstrap */
#       define BOOTP_BCAST      0x8000          /* ? */
       IP4_t           cip;            /* Client IP */
       IP4_t           yip;            /* Your IP */
       IP4_t           sip;            /* IP to use for next boot stage */
       IP4_t           gip;            /* Relay IP ? */
       MAC_ADDR        CAddr;          /* Client hardware address */
       uint8_t         Sname[64];      /* Server's hostname (Optional) */
       uint8_t         bootfile[128];  /* boot filename */
       union {
#               if 1
#               define BOOTP_DHCPVEND  1024    /* DHCP extended vendor
                                                 field size */
#               else
#               define BOOTP_DHCPVEND  312      /* DHCP standard vendor
                                                  field size */
#               endif
               uint8_t         d[BOOTP_DHCPVEND]; /* raw array of
                                                     vendor/dhcp options */
               struct {
                       uint8_t         magic[4];  /* DHCP magic cookie */
#                       ifndef          VM_RFC1048
#                       define          VM_RFC1048      0x63825363L     /* ? */
#                       endif
                       uint32_t        flags;     /* bootp flags/opcodes */
                       uint8_t         pad[56];   /* I don't think intel
                                                     knows what a union
                                                     does... */
               } v;
       } vendor;
} __packed BOOTPLAYER;

#define PXENV_RESTART_TFTP              0x0073
#define t_PXENV_RESTART_TFTP            t_PXENV_TFTP_READ_FILE

#define PXENV_START_BASE                0x0075
typedef struct {
       PXENV_STATUS_t  Status;
} __packed t_PXENV_START_BASE;

#define PXENV_STOP_BASE                 0x0076
typedef struct {
       PXENV_STATUS_t  Status;
} __packed t_PXENV_STOP_BASE;

#define PXENV_STATUS_SUCCESS            0
#define PXENV_STATUS_FAILURE            1
/* ...there are tons more, but we don't really care about them right now... */