Hi, I've checked the archives for my issue, and while there is relevant discussion, the problem the original poster was asking about didn't seem to have been resolved then either (~2 years ago). At any rate, basically what I'm trying to do is send (possibly receive) UDP packets via the PXE stack using the com32 API (using version 3.11 of syslinux). I have followed both the comboot API doc and the aforementioned thread; however they disagree on which registers are used for which bits of data in the setup for __intcall(). According to the comboot doc, to call the PXE stack's 'get cached info' function: Input: AX 0009h BX PXE function number ES:DI PXE data buffer Output: AX PXE return status code or, in com32 terms (the PXE call argument struct has been copied into the bounce buffer and the buffer field of the PXE call argument struct is setup to point into the bounce buffer as well): inputRegs.es = SEG(__com32.cs_bounce); inputRegs.edi.w[0] = OFFS(__com32.cs_bounce); inputRegs.eax.w[0] = 0x0009; /* call PXE stack */ inputRegs.ebx.w[0] = 0x0071; /* PXENV_GET_CACHED_INFO opcode */ __intcall(0x22, &inputRegs, &outputRegs); However, when setup this way, 'outputRegs.eax.w[0]' contains 'PXENV_EXIT_FAILURE' (and the status field of the PXE call argument struct indicates failure as well). The instructions from the previous thread on this topic are contrary to that documentation and indicate something more like (not sure about the PXE opcode being in edi, of course, but that wasn't specified in the thread): inputRegs.es = SEG(__com32.cs_bounce); inputRegs.ebx.w[0] = OFFS(__com32.cs_bounce); inputRegs.eax.w[0] = 0x0009; /* call PXE stack */ inputRegs.edi.w[0] = 0x0071; /* PXENV_GET_CACHED_INFO opcode */ __intcall(0x22, &inputRegs, &outputRegs); In this case, the call claims to succeed (eax contains 'PXENV_EXIT_SUCCESS' and the status field of the argument struct claims 'PXENV_STATUS_SUCCESS'), however the buffer that would receive the cached info (the BOOTPLAYER struct) seems to have all 0's. Has anyone successfully called the PXE stack from com32 (or, at least, can anyone help)? Thanks in advance, Jesse __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
Hi, I've checked the archives for my issue, and while there is relevant discussion, the problem the original poster was asking about didn't seem to have been resolved then either (~2 years ago). At any rate, basically what I'm trying to do is send (possibly receive) UDP packets via the PXE stack using the com32 API (using version 3.11 of syslinux). I have followed both the comboot API doc and the aforementioned thread; however they disagree on which registers are used for which bits of data in the setup for __intcall(). According to the comboot doc, to call the PXE stack's 'get cached info' function: Input: AX 0009h BX PXE function number ES:DI PXE data buffer Output: AX PXE return status code or, in com32 terms (the PXE call argument struct has been copied into the bounce buffer and the buffer field of the PXE call argument struct is setup to point into the bounce buffer as well): inputRegs.es = SEG(__com32.cs_bounce); inputRegs.edi.w[0] = OFFS(__com32.cs_bounce); inputRegs.eax.w[0] = 0x0009; /* call PXE stack */ inputRegs.ebx.w[0] = 0x0071; /* PXENV_GET_CACHED_INFO opcode */ __intcall(0x22, &inputRegs, &outputRegs); However, when setup this way, 'outputRegs.eax.w[0]' contains 'PXENV_EXIT_FAILURE' (and the status field of the PXE call argument struct indicates failure as well). The instructions from the previous thread on this topic are contrary to that documentation and indicate something more like (not sure about the PXE opcode being in edi, of course, but that wasn't specified in the thread): inputRegs.es = SEG(__com32.cs_bounce); inputRegs.ebx.w[0] = OFFS(__com32.cs_bounce); inputRegs.eax.w[0] = 0x0009; /* call PXE stack */ inputRegs.edi.w[0] = 0x0071; /* PXENV_GET_CACHED_INFO opcode */ __intcall(0x22, &inputRegs, &outputRegs); In this case, the call claims to succeed (eax contains 'PXENV_EXIT_SUCCESS' and the status field of the argument struct claims 'PXENV_STATUS_SUCCESS'), however the buffer that would receive the cached info (the BOOTPLAYER struct) seems to have all 0's. Has anyone successfully called the PXE stack from com32 (or, at least, can anyone help)? Thanks in advance, Jesse __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
Apologies in advance for the shoddy quoting of your reply (I've put '>> ' in front of your reply sections).... ----- Original Message ---- From: H. Peter Anvin <hpa at zytor.com> To: jesse barker <jessebarker5 at yahoo.com> Cc: syslinux at zytor.com Sent: Friday, January 5, 2007 9:26:06 PM Subject: Re: [syslinux] PXE stack access via com32 jesse barker wrote:> Hi, > > I've checked the archives for my issue, and while there is relevant discussion, the problem the original poster was asking about didn't seem to have been resolved then either (~2 years ago). At any rate, basically what I'm trying to do is send (possibly receive) UDP packets via the PXE stack using the com32 API (using version 3.11 of syslinux). I have followed both the comboot API doc and the aforementioned thread; however they disagree on which registers are used for which bits of data in the setup for __intcall(). According to the comboot doc, to call the PXE stack's 'get cached info' function: > > Input: AX 0009h > BX PXE function number > ES:DI PXE data buffer > Output: AX PXE return status code > > or, in com32 terms (the PXE call argument struct has been copied into the > bounce buffer and the buffer field of the PXE call argument struct is setup to > point into the bounce buffer as well): > > inputRegs.es = SEG(__com32.cs_bounce); > inputRegs.edi.w[0] = OFFS(__com32.cs_bounce); > inputRegs.eax.w[0] = 0x0009; /* call PXE stack */ > inputRegs.ebx.w[0] = 0x0071; /* PXENV_GET_CACHED_INFO opcode */ > > __intcall(0x22, &inputRegs, &outputRegs); > > However, when setup this way, 'outputRegs.eax.w[0]' contains 'PXENV_EXIT_FAILURE' (and the status field of the PXE call argument struct indicates failure as well). The instructions from the previous thread on this topic are contrary to that documentation and indicate something more > like (not sure about the PXE opcode being in edi, of course, but that wasn't specified in the thread)>> What's in __com32.cs_bounce at this point? It's expected to point to a >> s_PXENV_GET_CACHED_INFO (PXE 2.1 spec page 49) structure, which has been >> filled in by the caller. It is NOT the buffer in which you expect the >> data to be stored!I started with a PXENV_GET_CACHED_INFO struct as described in the spec (version 2.1). I filled it out like this: s_PXENV_GET_CACHED_INFO args; BOOTPLAYER cachedInfo; /* As described on page 50 of PXE 2.1 */ memset(&args, 0, sizeof(args)); memset(&cachedInfo, 0, sizeof(cachedInfo)); args.PacketType = PXENV_PACKET_TYPE_DHCP_ACK; /* 2 */ args.BufferSize = sizeof(cachedInfo); args.Buffer.segment = SEG(&cachedInfo); args.Buffer.offset = OFFS(&cachedInfo); memcpy(__com32.cs_bounce, &args, sizeof(args); inputRegs.es = SEG(__com32.cs_bounce); inputRegs.edi.w[0] = OFFS(__com32.cs_bounce); inputRegs.eax.w[0] = 0x0009; /* call PXE stack */ inputRegs.ebx.w[0] = 0x0071; /* PXENV_GET_CACHED_INFO opcode */ __intcall(0x22, &inputRegs, &outputRegs); And then, as I say, eax contains 'PXENV_EXIT_FAILURE' (and the status field contains 'PXENV_STATUS_FAILURE'). While debugging this, I noticed that the pointer to the BOOTPLAYER struct (&cachedInfo) had some more significant bits than could be used by 'SEG()' and 'OFFS()' (i.e. the original pointer could not be reconstructed from the segment and offset values in the argument struct), so I moved to using the bounce buffer to contain both structs and copied appropriately, though, that did not seem to have made a difference.> > inputRegs.es = SEG(__com32.cs_bounce); > inputRegs.ebx.w[0] = OFFS(__com32.cs_bounce); > inputRegs.eax.w[0] = 0x0009; /* call PXE stack */ > inputRegs.edi.w[0] = 0x0071; /* PXENV_GET_CACHED_INFO opcode */ > > __intcall(0x22, &inputRegs, &outputRegs); > > In this case, the call claims to succeed (eax contains 'PXENV_EXIT_SUCCESS' and the status field of the argument struct claims 'PXENV_STATUS_SUCCESS'), however the buffer that would receive the cached info (the BOOTPLAYER struct) seems to have all 0's.>> This is just plain wrong. You're with a very high likelihood calling >> PXE function zero (PXENV_START_UNDI), which is a totally different ball >> of wax.This was just an experiment. I felt I had to try both permutations given the difference between the comboot API documentation and your feedback on the prior thread on this topic (which was contrary to the docs). Thanks again for your feedback, Jesse __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
----- Original Message ---- From: H. Peter Anvin <hpa at zytor.com> To: jesse barker <jessebarker5 at yahoo.com> Cc: syslinux at zytor.com Sent: Saturday, January 6, 2007 11:16:22 AM Subject: Re: [syslinux] PXE stack access via com32 jesse barker wrote:> > I started with a PXENV_GET_CACHED_INFO struct as described in the spec (version 2.1). I filled it out like this: > > s_PXENV_GET_CACHED_INFO args; > BOOTPLAYER cachedInfo; /* As described on page 50 of PXE 2.1 */ > > memset(&args, 0, sizeof(args)); > memset(&cachedInfo, 0, sizeof(cachedInfo)); > > args.PacketType = PXENV_PACKET_TYPE_DHCP_ACK; /* 2 */ > args.BufferSize = sizeof(cachedInfo); > args.Buffer.segment = SEG(&cachedInfo); > args.Buffer.offset = OFFS(&cachedInfo); > > memcpy(__com32.cs_bounce, &args, sizeof(args);>> cachedInfo also needs to be in the bounce buffer! Here you're >> allocating it out of high memory, so the SEG:OFFS pointer that it >> produces is totally random (and invalid.)Right. That detail was at the end of my previous response:> And then, as I say, eax contains 'PXENV_EXIT_FAILURE' (and the statusfield contains> 'PXENV_STATUS_FAILURE'). While debugging this, Inoticed that the pointer to the BOOTPLAYER> struct (&cachedInfo) hadsome more significant bits than could be used by 'SEG()' and 'OFFS()'> (i.e. the original pointer could not be reconstructed from the segmentand offset values in the argument struct),> so I moved to using thebounce buffer to contain both structs and copied appropriately, though, that did not seem> to have made a difference.In reailty what I've done is something like: void* pxeArgs = __com32.cs_bounce+sizeof(cachedInfo); void* pxeData = __com32.cs_bounce; args.Buffer.segment = SEG(pxeData); args.Buffer.offset = OFFS(pxeData); memcpy(pxeArgs, &args, sizeof(args)); And then followed with the register settings as previously described where: inputRegs.es = SEG(pxeArgs); inputRegs.edi.w[0] = OFFS(pxeArgs); But, again, this doesn't seem to have made a difference. I still get 'PXENV_EXIT_FAILURE' and 'PXENV_STATUS_FAILURE' on return from __intcall(). cheers, Jesse __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
Also, it's worth noting that upon return from intcall(), outputRegs.eflags.l == 0x2, which isn't a documented value (at least not in the docs in version 3.11 or on the web docs). Thanks again, Jesse ----- Original Message ---- From: jesse barker <jessebarker5 at yahoo.com> To: H. Peter Anvin <hpa at zytor.com> Cc: syslinux at zytor.com Sent: Saturday, January 6, 2007 11:30:07 AM Subject: Re: [syslinux] PXE stack access via com32 ----- Original Message ---- From: H. Peter Anvin <hpa at zytor.com> To: jesse barker <jessebarker5 at yahoo.com> Cc: syslinux at zytor.com Sent: Saturday, January 6, 2007 11:16:22 AM Subject: Re: [syslinux] PXE stack access via com32 jesse barker wrote:> > I started with a PXENV_GET_CACHED_INFO struct as described in the spec (version 2.1). I filled it out like this: > > s_PXENV_GET_CACHED_INFO args; > BOOTPLAYER cachedInfo; /* As described on page 50 of PXE 2.1 */ > > memset(&args, 0, sizeof(args)); > memset(&cachedInfo, 0, sizeof(cachedInfo)); > > args.PacketType = PXENV_PACKET_TYPE_DHCP_ACK; /* 2 */ > args.BufferSize = sizeof(cachedInfo); > args.Buffer.segment = SEG(&cachedInfo); > args.Buffer.offset = OFFS(&cachedInfo); > > memcpy(__com32.cs_bounce, &args, sizeof(args);>> cachedInfo also needs to be in the bounce buffer! Here you're >> allocating it out of high memory, so the SEG:OFFS pointer that it >> produces is totally random (and invalid.)Right. That detail was at the end of my previous response:> And then, as I say, eax contains 'PXENV_EXIT_FAILURE' (and the statusfield contains> 'PXENV_STATUS_FAILURE'). While debugging this, Inoticed that the pointer to the BOOTPLAYER> struct (&cachedInfo) hadsome more significant bits than could be used by 'SEG()' and 'OFFS()'> (i.e. the original pointer could not be reconstructed from the segmentand offset values in the argument struct),> so I moved to using thebounce buffer to contain both structs and copied appropriately, though, that did not seem> to have made a difference.In reailty what I've done is something like: void* pxeArgs = __com32.cs_bounce+sizeof(cachedInfo); void* pxeData = __com32.cs_bounce; args.Buffer.segment = SEG(pxeData); args.Buffer.offset = OFFS(pxeData); memcpy(pxeArgs, &args, sizeof(args)); And then followed with the register settings as previously described where: inputRegs.es = SEG(pxeArgs); inputRegs.edi.w[0] = OFFS(pxeArgs); But, again, this doesn't seem to have made a difference. I still get 'PXENV_EXIT_FAILURE' and 'PXENV_STATUS_FAILURE' on return from __intcall(). cheers, Jesse __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com _______________________________________________ SYSLINUX mailing list Submissions to SYSLINUX at zytor.com Unsubscribe or set options at: http://www.zytor.com/mailman/listinfo/syslinux Please do not send private replies to mailing list traffic. __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
----- Original Message ---- From: H. Peter Anvin <hpa at zytor.com> To: jesse barker <jessebarker5 at yahoo.com> Cc: syslinux at zytor.com Sent: Monday, January 8, 2007 9:27:49 AM Subject: Re: [syslinux] PXE stack access via com32 jesse barker wrote:> Also, it's worth noting that upon return from intcall(), outputRegs.eflags.l == 0x2, which isn't a documented value (at least not in the docs in version 3.11 or on the web docs).>> What do you mean "it's not a documented value"? It's the EFLAGS >> register, which is documented in the processor documentation; bit 1 is >> always set in EFLAGS.Sorry, I was referring strictly to the comboot API docs which doesn't define anything to interpret bit 1 of eflags (I was loosely hoping it might indicate some undocumented error). At any rate, have you seen anything in my description of what I'm seeing that might give some indication of what's wrong? Do you (or anyone that you know is using this functionality) have any (com32) examples of PXE stack access that are known to work? I might be able to work backwards from there (at this point I have nothing to indicate incorrect use of the API, unless one of the data structure definitions in the PXE spec is wrong). cheers, Jesse __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
Peter, Thanks for all of your help. Nearly simultaneous with your last reply, I took a chance and set the buffer size to 0, and got back success (but, of course, no valid cached info, due to having provided a zero-sized buffer). When I got your reply, I was definitely reassured to see precious little difference between your code and mine (including the PXENV argument struct). It turns out that the discrepancy that made all the difference (setting pxeStackArgs.buffer_size == sizeof(BOOTPLAYER)) was based upon the questionable definition of 'BOOTPLAYER' in the PXE spec itself. Because of the vendor details union definition, I derived a value for 'BOOTP_DHCPVEND' based upon the struct portion, rather than researching the real value more thoroughly, so I ended up with a buffer size that was too small for the reply data, and it failed (my bad). cheers, Jesse ----- Original Message ---- From: H. Peter Anvin <hpa at zytor.com> To: jesse barker <jessebarker5 at yahoo.com> Cc: syslinux at zytor.com Sent: Monday, January 8, 2007 10:39:16 AM Subject: Re: [syslinux] PXE stack access via com32 jesse barker wrote:> > Sorry, I was referring strictly to the comboot API docs which doesn't define anything to interpret bit 1 of eflags (I was loosely hoping it might indicate some undocumented error). > > At any rate, have you seen anything in my description of what I'm seeing that might give some indication of what's wrong? Do you (or anyone that you know is using this functionality) have any (com32) examples of PXE stack access that are known to work? I might be able to work backwards from there (at this point I have nothing to indicate incorrect use of the API, unless one of the data structure definitions in the PXE spec is wrong). >This program seems to work for me. -hpa /* ----------------------------------------------------------------------- * * * Copyright 2007 H. Peter Anvin - All Rights Reserved * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall * be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * ----------------------------------------------------------------------- */ /* * pxetest.c * * Test of accessing the PXE stack from COM32; specifically obtain the * cached DHCP return packet. */ #include <inttypes.h> #include <com32.h> #include <stdio.h> #include <string.h> #include <console.h> struct s_PXENV_GET_CACHED_INFO { uint16_t Status; uint16_t PacketType; uint16_t BufferSize; uint16_t Buffer_offs, Buffer_seg; uint16_t BufferLimit; }; #define PXENV_PACKET_TYPE_DHCP_DISCOVER 1 #define PXENV_PACKET_TYPE_DHCP_ACK 2 #define PXENV_PACKET_TYPE_DHCP_REPLY 3 #define DHCP_MAX_PACKET 2048 static int get_dhcp_packet(char *buf) { static com32sys_t rin; com32sys_t rout; char *bufp = __com32.cs_bounce + sizeof(struct s_PXENV_GET_CACHED_INFO); struct s_PXENV_GET_CACHED_INFO *parm = (void *)__com32.cs_bounce; rin.eax.w[0] = 0x0009; rin.ebx.w[0] = 0x0071; /* PXENV_GET_CACHED_INFO */ rin.edi.w[0] = OFFS(parm); rin.es = SEG(parm); memset(parm, 0, sizeof *parm); parm->PacketType = PXENV_PACKET_TYPE_DHCP_ACK; parm->Buffer_offs = OFFS(bufp); parm->Buffer_seg = SEG(bufp); parm->BufferSize = DHCP_MAX_PACKET; __intcall(0x22, &rin, &rout); if ( rout.eflags.l & EFLAGS_CF ) { printf("Unable to invoke PXE stack\n"); return -1; } if ( rout.eax.w[0] ) { printf("PXE stack returned exit code %d\n", rout.eax.w[0]); return -1; } memcpy(buf, bufp, parm->BufferSize); return parm->BufferSize; } int main(void) { char pxe_packet[DHCP_MAX_PACKET]; int i, j, len; openconsole(&dev_stdcon_r, &dev_stdcon_w); if ((len = get_dhcp_packet(pxe_packet)) < 0) return 1; for (i = 0; i < len; i += 16) { for (j = 0; j < 16; j++) { if (i+j >= len) break; if (j) putchar(' '); printf("%02x", pxe_packet[i+j]); } putchar('\n'); } return 0; } __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com