glue.c revision 176481
1176348Smarcel/*- 2176348Smarcel * Copyright (c) 2007 Semihalf, Rafal Jaworowski <raj@semihalf.com> 3176348Smarcel * All rights reserved. 4176348Smarcel * 5176348Smarcel * Redistribution and use in source and binary forms, with or without 6176348Smarcel * modification, are permitted provided that the following conditions 7176348Smarcel * are met: 8176348Smarcel * 1. Redistributions of source code must retain the above copyright 9176348Smarcel * notice, this list of conditions and the following disclaimer. 10176348Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11176348Smarcel * notice, this list of conditions and the following disclaimer in the 12176348Smarcel * documentation and/or other materials provided with the distribution. 13176348Smarcel * 14176348Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15176348Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16176348Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17176348Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18176348Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19176348Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20176348Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21176348Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22176348Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23176348Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24176348Smarcel * SUCH DAMAGE. 25176348Smarcel */ 26176348Smarcel 27176348Smarcel#include <sys/cdefs.h> 28176348Smarcel__FBSDID("$FreeBSD: head/sys/boot/uboot/lib/glue.c 176481 2008-02-23 17:56:17Z marcel $"); 29176348Smarcel 30176348Smarcel#include <stand.h> 31176348Smarcel#include "api_public.h" 32176481Smarcel#include "glue.h" 33176348Smarcel 34176481Smarcel#define DEBUG 35176348Smarcel#undef DEBUG 36176348Smarcel 37176348Smarcel#ifdef DEBUG 38176348Smarcel#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0) 39176348Smarcel#else 40176348Smarcel#define debugf(fmt, args...) 41176348Smarcel#endif 42176348Smarcel 43176481Smarcel/* Some random address used by U-Boot. */ 44176481Smarcelextern long uboot_address; 45176348Smarcel 46176348Smarcel/* crc32 stuff stolen from lib/libdisk/write_ia64_disk.c */ 47176348Smarcelstatic uint32_t crc32_tab[] = { 48176348Smarcel 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 49176348Smarcel 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 50176348Smarcel 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 51176348Smarcel 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 52176348Smarcel 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 53176348Smarcel 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 54176348Smarcel 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 55176348Smarcel 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 56176348Smarcel 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 57176348Smarcel 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 58176348Smarcel 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 59176348Smarcel 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 60176348Smarcel 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 61176348Smarcel 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 62176348Smarcel 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 63176348Smarcel 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 64176348Smarcel 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 65176348Smarcel 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 66176348Smarcel 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 67176348Smarcel 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 68176348Smarcel 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 69176348Smarcel 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 70176348Smarcel 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 71176348Smarcel 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 72176348Smarcel 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 73176348Smarcel 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 74176348Smarcel 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 75176348Smarcel 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 76176348Smarcel 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 77176348Smarcel 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 78176348Smarcel 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 79176348Smarcel 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 80176348Smarcel 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 81176348Smarcel 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 82176348Smarcel 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 83176348Smarcel 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 84176348Smarcel 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 85176348Smarcel 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 86176348Smarcel 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 87176348Smarcel 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 88176348Smarcel 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 89176348Smarcel 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 90176348Smarcel 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 91176348Smarcel}; 92176348Smarcel 93176348Smarcelstatic uint32_t 94176348Smarcelcrc32(const void *buf, size_t size) 95176348Smarcel{ 96176348Smarcel const uint8_t *p; 97176348Smarcel uint32_t crc; 98176348Smarcel 99176348Smarcel p = buf; 100176348Smarcel crc = ~0U; 101176348Smarcel 102176348Smarcel while (size--) 103176348Smarcel crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 104176348Smarcel 105176348Smarcel return (crc ^ ~0U); 106176348Smarcel} 107176348Smarcel 108176348Smarcel 109176348Smarcelstatic int valid_sig(struct api_signature *sig) 110176348Smarcel{ 111176348Smarcel uint32_t checksum; 112176348Smarcel struct api_signature s; 113176348Smarcel 114176348Smarcel if (sig == NULL) 115176348Smarcel return 0; 116176348Smarcel /* 117176348Smarcel * Clear the checksum field (in the local copy) so as to calculate the 118176348Smarcel * CRC with the same initial contents as at the time when the sig was 119176348Smarcel * produced 120176348Smarcel */ 121176348Smarcel s = *sig; 122176348Smarcel s.checksum = 0; 123176348Smarcel 124176348Smarcel checksum = crc32((void *)&s, sizeof(struct api_signature)); 125176348Smarcel 126176348Smarcel if (checksum != sig->checksum) 127176348Smarcel return 0; 128176348Smarcel 129176348Smarcel return 1; 130176348Smarcel} 131176348Smarcel 132176348Smarcel/* 133176348Smarcel * Searches for the U-Boot API signature 134176348Smarcel * 135176348Smarcel * returns 1/0 depending on found/not found result 136176348Smarcel */ 137176348Smarcelint api_search_sig(struct api_signature **sig) { 138176348Smarcel 139176481Smarcel unsigned char *sp, *spend; 140176348Smarcel 141176348Smarcel if (sig == NULL) 142176348Smarcel return 0; 143176348Smarcel 144176481Smarcel if (uboot_address == 0) 145176481Smarcel uboot_address = 255 * 1024 * 1024; 146176348Smarcel 147176481Smarcel sp = (void *)(uboot_address & ~0x000fffff); 148176481Smarcel spend = sp + 0x00100000 - API_SIG_MAGLEN; 149176481Smarcel while (sp < spend) { 150176348Smarcel if (!bcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) { 151176348Smarcel *sig = (struct api_signature *)sp; 152176348Smarcel if (valid_sig(*sig)) 153176348Smarcel return 1; 154176348Smarcel } 155176348Smarcel sp += API_SIG_MAGLEN; 156176348Smarcel } 157176348Smarcel 158176348Smarcel *sig = NULL; 159176348Smarcel return 0; 160176348Smarcel} 161176348Smarcel 162176348Smarcel/**************************************** 163176348Smarcel * 164176348Smarcel * console 165176348Smarcel * 166176348Smarcel ****************************************/ 167176348Smarcel 168176348Smarcelint ub_getc(void) 169176348Smarcel{ 170176348Smarcel int c; 171176348Smarcel 172176348Smarcel if (!syscall(API_GETC, NULL, (uint32_t)&c)) 173176348Smarcel return -1; 174176348Smarcel 175176348Smarcel return c; 176176348Smarcel} 177176348Smarcel 178176348Smarcelint ub_tstc(void) 179176348Smarcel{ 180176348Smarcel int t; 181176348Smarcel 182176348Smarcel if (!syscall(API_TSTC, NULL, (uint32_t)&t)) 183176348Smarcel return -1; 184176348Smarcel 185176348Smarcel return t; 186176348Smarcel} 187176348Smarcel 188176348Smarcelvoid ub_putc(char c) 189176348Smarcel{ 190176348Smarcel syscall(API_PUTC, NULL, (uint32_t)&c); 191176348Smarcel} 192176348Smarcel 193176348Smarcelvoid ub_puts(const char *s) 194176348Smarcel{ 195176348Smarcel syscall(API_PUTS, NULL, (uint32_t)s); 196176348Smarcel} 197176348Smarcel 198176348Smarcel/**************************************** 199176348Smarcel * 200176348Smarcel * system 201176348Smarcel * 202176348Smarcel ****************************************/ 203176348Smarcel 204176348Smarcelvoid ub_reset(void) 205176348Smarcel{ 206176348Smarcel syscall(API_RESET, NULL); 207176348Smarcel} 208176348Smarcel 209176348Smarcel 210176348Smarcel#define MR_MAX 5 211176348Smarcelstatic struct mem_region mr[MR_MAX]; 212176348Smarcelstatic struct sys_info si; 213176348Smarcel 214176348Smarcelstruct sys_info * ub_get_sys_info(void) 215176348Smarcel{ 216176348Smarcel int err = 0; 217176348Smarcel 218176348Smarcel memset(&si, 0, sizeof(struct sys_info)); 219176348Smarcel si.mr = mr; 220176348Smarcel si.mr_no = MR_MAX; 221176348Smarcel memset(&mr, 0, sizeof(mr)); 222176348Smarcel 223176348Smarcel if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si)) 224176348Smarcel return NULL; 225176348Smarcel 226176348Smarcel return ((err) ? NULL : &si); 227176348Smarcel} 228176348Smarcel 229176348Smarcel 230176348Smarcel/**************************************** 231176348Smarcel * 232176348Smarcel * timing 233176348Smarcel * 234176348Smarcel ****************************************/ 235176348Smarcel 236176348Smarcelvoid ub_udelay(unsigned long usec) 237176348Smarcel{ 238176348Smarcel syscall(API_UDELAY, NULL, &usec); 239176348Smarcel} 240176348Smarcel 241176348Smarcelunsigned long ub_get_timer(unsigned long base) 242176348Smarcel{ 243176348Smarcel unsigned long cur; 244176348Smarcel 245176348Smarcel if (!syscall(API_GET_TIMER, NULL, &cur, &base)) 246176348Smarcel return 0; 247176348Smarcel 248176348Smarcel return cur; 249176348Smarcel} 250176348Smarcel 251176348Smarcel 252176348Smarcel/**************************************************************************** 253176348Smarcel * 254176348Smarcel * devices 255176348Smarcel * 256176348Smarcel * Devices are identified by handles: numbers 0, 1, 2, ..., MAX_DEVS-1 257176348Smarcel * 258176348Smarcel ***************************************************************************/ 259176348Smarcel 260176348Smarcel#define MAX_DEVS 6 261176348Smarcel 262176348Smarcelstatic struct device_info devices[MAX_DEVS]; 263176348Smarcel 264176348Smarcelstruct device_info * ub_dev_get(int i) 265176348Smarcel{ 266176348Smarcel return ((i < 0 || i >= MAX_DEVS) ? NULL : &devices[i]); 267176348Smarcel} 268176348Smarcel 269176348Smarcel/* 270176348Smarcel * Enumerates the devices: fills out device_info elements in the devices[] 271176348Smarcel * array. 272176348Smarcel * 273176348Smarcel * returns: number of devices found 274176348Smarcel */ 275176348Smarcelint ub_dev_enum(void) 276176348Smarcel{ 277176348Smarcel struct device_info *di; 278176348Smarcel int n = 0; 279176348Smarcel 280176348Smarcel memset(&devices, 0, sizeof(struct device_info) * MAX_DEVS); 281176348Smarcel di = &devices[0]; 282176348Smarcel 283176348Smarcel if (!syscall(API_DEV_ENUM, NULL, di)) 284176348Smarcel return 0; 285176348Smarcel 286176348Smarcel while (di->cookie != NULL) { 287176348Smarcel 288176348Smarcel if (++n >= MAX_DEVS) 289176348Smarcel break; 290176348Smarcel 291176348Smarcel /* take another device_info */ 292176348Smarcel di++; 293176348Smarcel 294176348Smarcel /* pass on the previous cookie */ 295176348Smarcel di->cookie = devices[n - 1].cookie; 296176348Smarcel 297176348Smarcel if (!syscall(API_DEV_ENUM, NULL, di)) 298176348Smarcel return 0; 299176348Smarcel } 300176348Smarcel 301176348Smarcel return n; 302176348Smarcel} 303176348Smarcel 304176348Smarcel 305176348Smarcel/* 306176348Smarcel * handle: 0-based id of the device 307176348Smarcel * 308176348Smarcel * returns: 0 when OK, err otherwise 309176348Smarcel */ 310176348Smarcelint ub_dev_open(int handle) 311176348Smarcel{ 312176348Smarcel struct device_info *di; 313176348Smarcel int err = 0; 314176348Smarcel 315176348Smarcel if (handle < 0 || handle >= MAX_DEVS) 316176348Smarcel return API_EINVAL; 317176348Smarcel 318176348Smarcel di = &devices[handle]; 319176348Smarcel if (!syscall(API_DEV_OPEN, &err, di)) 320176348Smarcel return -1; 321176348Smarcel 322176348Smarcel return err; 323176348Smarcel} 324176348Smarcel 325176348Smarcelint ub_dev_close(int handle) 326176348Smarcel{ 327176348Smarcel struct device_info *di; 328176348Smarcel 329176348Smarcel if (handle < 0 || handle >= MAX_DEVS) 330176348Smarcel return API_EINVAL; 331176348Smarcel 332176348Smarcel di = &devices[handle]; 333176348Smarcel if (!syscall(API_DEV_CLOSE, NULL, di)) 334176348Smarcel return -1; 335176348Smarcel 336176348Smarcel return 0; 337176348Smarcel} 338176348Smarcel 339176348Smarcel/* 340176348Smarcel * Validates device for read/write, it has to: 341176348Smarcel * 342176348Smarcel * - have sane handle 343176348Smarcel * - be opened 344176348Smarcel * 345176348Smarcel * returns: 0/1 accordingly 346176348Smarcel */ 347176348Smarcelstatic int dev_valid(int handle) 348176348Smarcel{ 349176348Smarcel if (handle < 0 || handle >= MAX_DEVS) 350176348Smarcel return 0; 351176348Smarcel 352176348Smarcel if (devices[handle].state != DEV_STA_OPEN) 353176348Smarcel return 0; 354176348Smarcel 355176348Smarcel return 1; 356176348Smarcel} 357176348Smarcel 358176348Smarcelstatic int dev_stor_valid(int handle) 359176348Smarcel{ 360176348Smarcel if (!dev_valid(handle)) 361176348Smarcel return 0; 362176348Smarcel 363176348Smarcel if (!(devices[handle].type & DEV_TYP_STOR)) 364176348Smarcel return 0; 365176348Smarcel 366176348Smarcel return 1; 367176348Smarcel} 368176348Smarcel 369176348Smarcelint ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start) 370176348Smarcel{ 371176348Smarcel struct device_info *di; 372176348Smarcel lbasize_t act_len; 373176348Smarcel int err = 0; 374176348Smarcel 375176348Smarcel if (!dev_stor_valid(handle)) 376176348Smarcel return API_ENODEV; 377176348Smarcel 378176348Smarcel di = &devices[handle]; 379176348Smarcel if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len)) 380176348Smarcel return -1; 381176348Smarcel 382176348Smarcel if (err) 383176348Smarcel return err; 384176348Smarcel 385176348Smarcel if (act_len != len) 386176348Smarcel return API_EIO; 387176348Smarcel 388176348Smarcel return 0; 389176348Smarcel} 390176348Smarcel 391176348Smarcelstatic int dev_net_valid(int handle) 392176348Smarcel{ 393176348Smarcel if (!dev_valid(handle)) 394176348Smarcel return 0; 395176348Smarcel 396176348Smarcel if (devices[handle].type != DEV_TYP_NET) 397176348Smarcel return 0; 398176348Smarcel 399176348Smarcel return 1; 400176348Smarcel} 401176348Smarcel 402176348Smarcelint ub_dev_recv(int handle, void *buf, int len) 403176348Smarcel{ 404176348Smarcel struct device_info *di; 405176348Smarcel int err = 0, act_len; 406176348Smarcel 407176348Smarcel if (!dev_net_valid(handle)) 408176348Smarcel return API_ENODEV; 409176348Smarcel 410176348Smarcel di = &devices[handle]; 411176348Smarcel if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len)) 412176348Smarcel return -1; 413176348Smarcel 414176348Smarcel if (err) 415176348Smarcel return -1; 416176348Smarcel 417176348Smarcel return act_len; 418176348Smarcel} 419176348Smarcel 420176348Smarcelint ub_dev_send(int handle, void *buf, int len) 421176348Smarcel{ 422176348Smarcel struct device_info *di; 423176348Smarcel int err = 0; 424176348Smarcel 425176348Smarcel if (!dev_net_valid(handle)) 426176348Smarcel return API_ENODEV; 427176348Smarcel 428176348Smarcel di = &devices[handle]; 429176348Smarcel if (!syscall(API_DEV_WRITE, &err, di, buf, &len)) 430176348Smarcel return -1; 431176348Smarcel 432176348Smarcel return err; 433176348Smarcel} 434176348Smarcel 435176348Smarcel/**************************************** 436176348Smarcel * 437176348Smarcel * env vars 438176348Smarcel * 439176348Smarcel ****************************************/ 440176348Smarcel 441176348Smarcelchar * ub_env_get(const char *name) 442176348Smarcel{ 443176348Smarcel char *value; 444176348Smarcel 445176348Smarcel if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value)) 446176348Smarcel return NULL; 447176348Smarcel 448176348Smarcel return value; 449176348Smarcel} 450176348Smarcel 451176348Smarcelvoid ub_env_set(const char *name, char *value) 452176348Smarcel{ 453176348Smarcel syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value); 454176348Smarcel} 455176348Smarcel 456176348Smarcel 457176348Smarcelstatic char env_name[256]; 458176348Smarcel 459176348Smarcelconst char * ub_env_enum(const char *last) 460176348Smarcel{ 461176348Smarcel const char *env, *str; 462176348Smarcel int i; 463176348Smarcel 464176348Smarcel env = NULL; 465176348Smarcel 466176348Smarcel /* 467176348Smarcel * It's OK to pass only the name piece as last (and not the whole 468176348Smarcel * 'name=val' string), since the API_ENUM_ENV call uses envmatch() 469176348Smarcel * internally, which handles such case 470176348Smarcel */ 471176348Smarcel if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env)) 472176348Smarcel return NULL; 473176348Smarcel 474176348Smarcel if (!env) 475176348Smarcel /* no more env. variables to enumerate */ 476176348Smarcel return NULL; 477176348Smarcel#if 0 478176348Smarcel if (last && strncmp(env, last, strlen(last)) == 0); 479176348Smarcel /* error, trying to enumerate non existing env. variable */ 480176348Smarcel return NULL; 481176348Smarcel#endif 482176348Smarcel 483176348Smarcel /* next enumerated env var */ 484176348Smarcel memset(env_name, 0, 256); 485176348Smarcel for (i = 0, str = env; *str != '=' && *str != '\0';) 486176348Smarcel env_name[i++] = *str++; 487176348Smarcel 488176348Smarcel env_name[i] = '\0'; 489176348Smarcel 490176348Smarcel return env_name; 491176348Smarcel} 492