176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ----------------------------------------------------------------------- *
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Copyright 2008 H. Peter Anvin - All Rights Reserved
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   This program is free software; you can redistribute it and/or modify
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   it under the terms of the GNU General Public License as published by
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Boston MA 02110-1301, USA; either version 2 of the License, or
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   (at your option) any later version; incorporated herein by reference.
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ----------------------------------------------------------------------- */
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * gpxecmd.c
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Invoke an arbitrary gPXE command, if available.
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <alloca.h>
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <inttypes.h>
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h>
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <console.h>
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <com32.h>
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h>
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <sys/gpxe.h>
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <syslinux/pxe_api.h>
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct segoff16 {
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    uint16_t offs, seg;
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct s_PXENV_FILE_EXEC {
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    uint16_t Status;
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct segoff16 Command;
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void gpxecmd(const char **args)
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char *q;
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct s_PXENV_FILE_EXEC *fx;
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    fx = lmalloc(sizeof *fx);
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!fx)
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return;
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    q = (char *)(fx + 1);
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    fx->Status = 1;
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    fx->Command.offs = OFFS(q);
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    fx->Command.seg = SEG(q);
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while (*args) {
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	q = stpcpy(q, *args);
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	*q++ = ' ';
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	args++;
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    *--q = '\0';
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    pxe_call(PXENV_FILE_EXEC, fx);
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* This should not return... */
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint main(int argc, const char *argv[])
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (argc < 2) {
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	printf("Usage: gpxecmd command...\n");
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return 1;
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!is_gpxe()) {
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	printf("gpxecmd: gPXE API not detected\n");
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return 1;
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    gpxecmd(argv + 1);
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 0;
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
81