/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* bos720 src/bos/usr/samples/ahafs/samplePrograms/kextEvProd/kexload.c 1.1 */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* Restricted Materials of IBM                                            */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2009                   */
/* All Rights Reserved                                                    */
/*                                                                        */
/* US Government Users Restricted Rights - Use, duplication or            */
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/********************************************************************
 * FUNCTIONS in this file kexload.c:
 *          kexload/main
 * PURPOSE: Kernel extension loader/unloader for AIX 3.1, 4.1, 5.3, 6.1
 * SYNTAX:  kexload <flag> <kexName>
 *    where  <flag> can be 1 of: l(=load), u(unload), q(query)
 * HOW TO COMPILE:  cc -o kexload kexload.c
 * EXECUTION ENVIRON.: Superuser privilege is required to execute this fcn
 * COPYRIGHT IBM CORP. 1990 to 2007 - All Rights Reserved
 * CHANGLOG: 2006/12/26, 2008/11/15 Joefon Jann
 ********************************************************************/
#include  <errno.h>         /* Header file for error numbers */
#include  <string.h>        /* String subroutines    */
#include  <sys/types.h>     /* AIX types             */
#include  <sys/stat.h>      /* stat subroutine       */
#include  <sys/sysconfig.h> /* sysconfig syscall     */
#include  <sys/device.h>    /* Defines the CFG_INIT & CFG_TERM const */
/* See if the following line is requried */
#include <unistd.h>

char *flags;
int  flagCt;

main(argc,argv)
int   argc;
char  *argv[];                  /* Argument list                      */
{
  struct  cfg_kmod    ckmod;   /* Data struct for sysconfig parm list */
  struct  cfg_load    cload;   /* Data struct for sysconfig parm list */
  struct  stat        statbuf; /* Buffer for stat subroutine call     */
  char    load_file[256], c;   /* Filename of the kernel extension    */
  int     rc;

  /* Fetch arguments passed to the executable & set the process priority */
  if (argc < 3)
  {
     printf ("SYNTAX: %s <flags> <kernel_extension>\n",argv[0]);
     exit(EINVAL);              /* Exit with error */
  }

  strcpy(load_file,argv[2]);
  if (stat(load_file,&statbuf) != 0)
  {  perror("stat");
     exit(-1);
  }
  flags  = argv[1];
  flagCt = strlen(flags);

  /*-------------------------------------------*/
  /* Set up the sysconfig load parameter list  */
  /*-------------------------------------------*/
  cload.path = load_file;       /* File name */
  cload.libpath = NULL;         /* No library */
  cload.kmid = 0;               /* Not kernel memory ID yet */

  /*-------------------------------------------------------------*/
  /* Main loop: read args & perform the requested flag/operation */
  /*-------------------------------------------------------------*/
  while(1)
  {
    if (flagCt > 0)
    {  c = *flags;
       flags++;
       flagCt--;
    }
    else
    {  c = 'e';
    }

    switch(c)
    {   /* Process input flag: */

      case 'l':
        /*-------------------------------*/
        /* l - Load the kernel extension */
        /*-------------------------------*/
        sysconfig(SYS_QUERYLOAD,&cload,sizeof(struct cfg_load)); /* queryload */
        if (cload.kmid != 0)    /* check if already loaded */
        {
            printf("Extension already loaded!\n"); /* print message if already loaded */
            exit (0);
        }

        if (sysconfig(SYS_SINGLELOAD,&cload,sizeof(struct cfg_load))) /* load it */
        {
            perror("sysconfig(SYS_SINGLELOAD)");
            exit (-1);
        }
        else
          printf("Extension loaded--kmid is %lx (base16) = %ld(base10)\n",
                                             cload.kmid, cload.kmid);

        /*------------------------------------------*/
        /* Configure the kernel extension (pin it)  */
        /*------------------------------------------*/
        ckmod.kmid = cload.kmid;  /* Move the kernel memory ID */
        ckmod.cmd = CFG_INIT;     /* Coniguration request      */
        ckmod.mdiptr = NULL;      /* No MDI                    */
        ckmod.mdilen = 0;

        if (rc = sysconfig(SYS_CFGKMOD,&ckmod,sizeof(ckmod)))
           perror("sysconfig(SYS_CFGKMOD)");
        printf ("rc from sysconfig(SYS_CFGMOD) is %d\n", rc);

        printf("Load done.\n");
        break;

    case 'u':
      /*---------------------------------*/
      /* u - Unload the kernel extension */
      /*---------------------------------*/
      sysconfig(SYS_QUERYLOAD,&cload,sizeof(struct cfg_load)); /* queryload */
      if (cload.kmid == 0)                /* Check if loaded      */
        printf("Extension not loaded\n"); /* Print message if not */
      else
      {
         /*---------------------------------------------*/
         /* Unconfigure the kernel extension (unpin it) */
         /*---------------------------------------------*/
         ckmod.kmid = cload.kmid; /* Move the kernel memory ID        */
         ckmod.cmd = CFG_TERM;    /* Unconfigure the kernel extension */
         ckmod.mdiptr = NULL;     /* No MDI(Machine Dependent Info    */
         ckmod.mdilen = 0;
         if (sysconfig(SYS_CFGKMOD,&ckmod,sizeof(ckmod)))
           perror("sysconfig(SYS_CFGKMOD)");

         /*------------------------------*/
         /* Unload the kernel extension  */
         /*------------------------------*/
         if (sysconfig(SYS_KULOAD,&cload,sizeof(struct cfg_load)))
            perror("sysconfig(SYS_KULOAD)");
         else
            printf("Unload Done.\n");
      }
      break;

    case 'q':
      /*---------------------------------------------------------------------*/
      /* q - Query the kernel extension (Check if it is loaded & print kmID) */
      /*---------------------------------------------------------------------*/
      sysconfig(SYS_QUERYLOAD,&cload,sizeof(struct cfg_load));
      if (cload.kmid == 0)
        printf("Extension not loaded\n");
      else
        printf("Extension loaded--kmid is %lx (base16) = %ld(base10)\n",
                            cload.kmid, cload.kmid);
      break;

    case 'e':       /* Terminate program request */
      exit(0);

    case '-':       /* Ignore dashes in the flag */
      break;

    default:        /* Invalid request           */
      printf("Unknown choice: %c\n", c);
      break;
    } /* End switch() */

  }   /* End while()  */
}     /* End main     */
