Index: head/sys/boot/efi/libefi/time.c =================================================================== --- head/sys/boot/efi/libefi/time.c (revision 306158) +++ head/sys/boot/efi/libefi/time.c (revision 306159) @@ -1,234 +1,234 @@ /*- * Copyright (c) 1999, 2000 * Intel Corporation. * 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. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * * This product includes software developed by Intel Corporation and * its contributors. * * 4. Neither the name of Intel Corporation or its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION 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 INTEL CORPORATION 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. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include /* // Accurate only for the past couple of centuries; // that will probably do. // // (#defines From FreeBSD 3.2 lib/libc/stdtime/tzfile.h) */ #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) #define SECSPERHOUR ( 60*60 ) #define SECSPERDAY (24 * SECSPERHOUR) void efi_time_init(void) { } void efi_time_fini(void) { } static time_t efi_time(EFI_TIME *ETime) { /* // These arrays give the cumulative number of days up to the first of the // month number used as the index (1 -> 12) for regular and leap years. // The value at index 13 is for the whole year. */ static time_t CumulativeDays[2][14] = { {0, 0, 31, 31 + 28, 31 + 28 + 31, 31 + 28 + 31 + 30, 31 + 28 + 31 + 30 + 31, 31 + 28 + 31 + 30 + 31 + 30, 31 + 28 + 31 + 30 + 31 + 30 + 31, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }, {0, 0, 31, 31 + 29, 31 + 29 + 31, 31 + 29 + 31 + 30, 31 + 29 + 31 + 30 + 31, 31 + 29 + 31 + 30 + 31 + 30, 31 + 29 + 31 + 30 + 31 + 30 + 31, 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31, 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30, 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }}; time_t UTime; int Year; /* // Do a santity check */ if ( ETime->Year < 1998 || ETime->Year > 2099 || ETime->Month == 0 || ETime->Month > 12 || ETime->Day == 0 || ETime->Month > 31 || ETime->Hour > 23 || ETime->Minute > 59 || ETime->Second > 59 || ETime->TimeZone < -1440 || (ETime->TimeZone > 1440 && ETime->TimeZone != 2047) ) { return (0); } /* // Years */ UTime = 0; for (Year = 1970; Year != ETime->Year; ++Year) { UTime += (CumulativeDays[isleap(Year)][13] * SECSPERDAY); } /* // UTime should now be set to 00:00:00 on Jan 1 of the file's year. // // Months */ UTime += (CumulativeDays[isleap(ETime->Year)][ETime->Month] * SECSPERDAY); /* // UTime should now be set to 00:00:00 on the first of the file's month and year // // Days -- Don't count the file's day */ UTime += (((ETime->Day > 0) ? ETime->Day-1:0) * SECSPERDAY); /* // Hours */ UTime += (ETime->Hour * SECSPERHOUR); /* // Minutes */ UTime += (ETime->Minute * 60); /* // Seconds */ UTime += ETime->Second; /* // EFI time is repored in local time. Adjust for any time zone offset to // get true UT */ if ( ETime->TimeZone != EFI_UNSPECIFIED_TIMEZONE ) { /* // TimeZone is kept in minues... */ UTime += (ETime->TimeZone * 60); } return UTime; } static int EFI_GetTimeOfDay( OUT struct timeval *tp, OUT struct timezone *tzp ) { EFI_TIME EfiTime; EFI_TIME_CAPABILITIES Capabilities; EFI_STATUS Status; /* // Get time from EFI */ Status = RS->GetTime(&EfiTime, &Capabilities); if (EFI_ERROR(Status)) return (-1); /* // Convert to UNIX time (ie seconds since the epoch */ tp->tv_sec = efi_time( &EfiTime ); tp->tv_usec = 0; /* EfiTime.Nanosecond * 1000; */ /* // Do something with the timezone if needed */ if (tzp) { tzp->tz_minuteswest = EfiTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE ? 0 : EfiTime.TimeZone; /* // This isn't quit right since it doesn't deal with EFI_TIME_IN_DAYLIGHT */ tzp->tz_dsttime = EfiTime.Daylight & EFI_TIME_ADJUST_DAYLIGHT ? 1 : 0; } return (0); } time_t time(time_t *tloc) { struct timeval tv; EFI_GetTimeOfDay(&tv, 0); if (tloc) *tloc = tv.tv_sec; return tv.tv_sec; } time_t -getsecs() +getsecs(void) { return time(0); } Index: head/sys/boot/efi/libefi/time_event.c =================================================================== --- head/sys/boot/efi/libefi/time_event.c (revision 306158) +++ head/sys/boot/efi/libefi/time_event.c (revision 306159) @@ -1,82 +1,82 @@ /*- * Copyright (c) 2016 Andrew Turner * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include static EFI_EVENT time_event; static uint64_t curtime; static void time_update(EFI_EVENT event, void *context) { curtime += 10; } void efi_time_init(void) { /* Create a timer event */ BS->CreateEvent(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, time_update, 0, &time_event); /* Use a 10ms timer */ BS->SetTimer(time_event, TimerPeriodic, 100000); } void efi_time_fini(void) { /* Cancel the timer */ BS->SetTimer(time_event, TimerCancel, 0); BS->CloseEvent(time_event); } time_t time(time_t *tloc) { time_t t; t = curtime / 1000; if (tloc != NULL) *tloc = t; return (t); } time_t -getsecs() +getsecs(void) { return time(0); } Index: head/sys/boot/i386/libi386/pxe.c =================================================================== --- head/sys/boot/i386/libi386/pxe.c (revision 306158) +++ head/sys/boot/i386/libi386/pxe.c (revision 306159) @@ -1,717 +1,717 @@ /*- * Copyright (c) 2000 Alfred Perlstein * Copyright (c) 2000 Paul Saab * Copyright (c) 2000 John Baldwin * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "btxv86.h" #include "pxe.h" /* * Allocate the PXE buffers statically instead of sticking grimy fingers into * BTX's private data area. The scratch buffer is used to send information to * the PXE BIOS, and the data buffer is used to receive data from the PXE BIOS. */ #define PXE_BUFFER_SIZE 0x2000 #define PXE_TFTP_BUFFER_SIZE 512 static char scratch_buffer[PXE_BUFFER_SIZE]; static char data_buffer[PXE_BUFFER_SIZE]; static pxenv_t *pxenv_p = NULL; /* PXENV+ */ static pxe_t *pxe_p = NULL; /* !PXE */ static BOOTPLAYER bootplayer; /* PXE Cached information. */ static int pxe_debug = 0; static int pxe_sock = -1; static int pxe_opens = 0; void pxe_enable(void *pxeinfo); static void (*pxe_call)(int func); static void pxenv_call(int func); static void bangpxe_call(int func); static int pxe_init(void); static int pxe_strategy(void *devdata, int flag, daddr_t dblk, size_t offset, size_t size, char *buf, size_t *rsize); static int pxe_open(struct open_file *f, ...); static int pxe_close(struct open_file *f); static void pxe_print(int verbose); static void pxe_cleanup(void); static void pxe_setnfshandle(char *rootpath); static void pxe_perror(int error); static int pxe_netif_match(struct netif *nif, void *machdep_hint); static int pxe_netif_probe(struct netif *nif, void *machdep_hint); static void pxe_netif_init(struct iodesc *desc, void *machdep_hint); static int pxe_netif_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout); static int pxe_netif_put(struct iodesc *desc, void *pkt, size_t len); static void pxe_netif_end(struct netif *nif); #ifdef OLD_NFSV2 int nfs_getrootfh(struct iodesc*, char*, u_char*); #else int nfs_getrootfh(struct iodesc*, char*, uint32_t*, u_char*); #endif extern struct netif_stats pxe_st[]; extern u_int16_t __bangpxeseg; extern u_int16_t __bangpxeoff; extern void __bangpxeentry(void); extern u_int16_t __pxenvseg; extern u_int16_t __pxenvoff; extern void __pxenventry(void); struct netif_dif pxe_ifs[] = { /* dif_unit dif_nsel dif_stats dif_private */ {0, 1, &pxe_st[0], 0} }; struct netif_stats pxe_st[NENTS(pxe_ifs)]; struct netif_driver pxenetif = { "pxenet", pxe_netif_match, pxe_netif_probe, pxe_netif_init, pxe_netif_get, pxe_netif_put, pxe_netif_end, pxe_ifs, NENTS(pxe_ifs) }; struct netif_driver *netif_drivers[] = { &pxenetif, NULL }; struct devsw pxedisk = { "pxe", DEVT_NET, pxe_init, pxe_strategy, pxe_open, pxe_close, noioctl, pxe_print, pxe_cleanup }; /* * This function is called by the loader to enable PXE support if we * are booted by PXE. The passed in pointer is a pointer to the * PXENV+ structure. */ void pxe_enable(void *pxeinfo) { pxenv_p = (pxenv_t *)pxeinfo; pxe_p = (pxe_t *)PTOV(pxenv_p->PXEPtr.segment * 16 + pxenv_p->PXEPtr.offset); pxe_call = NULL; } /* * return true if pxe structures are found/initialized, * also figures out our IP information via the pxe cached info struct */ static int pxe_init(void) { t_PXENV_GET_CACHED_INFO *gci_p; int counter; uint8_t checksum; uint8_t *checkptr; if(pxenv_p == NULL) return (0); /* look for "PXENV+" */ if (bcmp((void *)pxenv_p->Signature, S_SIZE("PXENV+"))) { pxenv_p = NULL; return (0); } /* make sure the size is something we can handle */ if (pxenv_p->Length > sizeof(*pxenv_p)) { printf("PXENV+ structure too large, ignoring\n"); pxenv_p = NULL; return (0); } /* * do byte checksum: * add up each byte in the structure, the total should be 0 */ checksum = 0; checkptr = (uint8_t *) pxenv_p; for (counter = 0; counter < pxenv_p->Length; counter++) checksum += *checkptr++; if (checksum != 0) { printf("PXENV+ structure failed checksum, ignoring\n"); pxenv_p = NULL; return (0); } /* * PXENV+ passed, so use that if !PXE is not available or * the checksum fails. */ pxe_call = pxenv_call; if (pxenv_p->Version >= 0x0200) { for (;;) { if (bcmp((void *)pxe_p->Signature, S_SIZE("!PXE"))) { pxe_p = NULL; break; } checksum = 0; checkptr = (uint8_t *)pxe_p; for (counter = 0; counter < pxe_p->StructLength; counter++) checksum += *checkptr++; if (checksum != 0) { pxe_p = NULL; break; } pxe_call = bangpxe_call; break; } } printf("\nPXE version %d.%d, real mode entry point ", (uint8_t) (pxenv_p->Version >> 8), (uint8_t) (pxenv_p->Version & 0xFF)); if (pxe_call == bangpxe_call) printf("@%04x:%04x\n", pxe_p->EntryPointSP.segment, pxe_p->EntryPointSP.offset); else printf("@%04x:%04x\n", pxenv_p->RMEntry.segment, pxenv_p->RMEntry.offset); gci_p = (t_PXENV_GET_CACHED_INFO *) scratch_buffer; bzero(gci_p, sizeof(*gci_p)); gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY; pxe_call(PXENV_GET_CACHED_INFO); if (gci_p->Status != 0) { pxe_perror(gci_p->Status); pxe_p = NULL; return (0); } bcopy(PTOV((gci_p->Buffer.segment << 4) + gci_p->Buffer.offset), &bootplayer, gci_p->BufferSize); return (1); } static int pxe_strategy(void *devdata, int flag, daddr_t dblk, size_t offset, size_t size, char *buf, size_t *rsize) { return (EIO); } static int pxe_open(struct open_file *f, ...) { va_list args; char *devname; /* Device part of file name (or NULL). */ char temp[FNAME_SIZE]; int error = 0; int i; va_start(args, f); devname = va_arg(args, char*); va_end(args); /* On first open, do netif open, mount, etc. */ if (pxe_opens == 0) { /* Find network interface. */ if (pxe_sock < 0) { pxe_sock = netif_open(devname); if (pxe_sock < 0) { printf("pxe_open: netif_open() failed\n"); return (ENXIO); } if (pxe_debug) printf("pxe_open: netif_open() succeeded\n"); } if (rootip.s_addr == 0) { /* * Do a bootp/dhcp request to find out where our * NFS/TFTP server is. Even if we dont get back * the proper information, fall back to the server * which brought us to life and a default rootpath. */ bootp(pxe_sock, BOOTP_PXE); if (rootip.s_addr == 0) rootip.s_addr = bootplayer.sip; netproto = NET_NFS; if (tftpip.s_addr != 0) { netproto = NET_TFTP; rootip.s_addr = tftpip.s_addr; } if (netproto == NET_NFS && !rootpath[0]) strcpy(rootpath, PXENFSROOTPATH); for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++) if (rootpath[i] == ':') break; if (i && i != FNAME_SIZE && rootpath[i] == ':') { rootpath[i++] = '\0'; if (inet_addr(&rootpath[0]) != INADDR_NONE) rootip.s_addr = inet_addr(&rootpath[0]); bcopy(&rootpath[i], &temp[0], strlen(&rootpath[i])+1); bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1); } setenv("boot.netif.ip", inet_ntoa(myip), 1); setenv("boot.netif.netmask", intoa(netmask), 1); setenv("boot.netif.gateway", inet_ntoa(gateip), 1); if (bootplayer.Hardware == ETHER_TYPE) { sprintf(temp, "%6D", bootplayer.CAddr, ":"); setenv("boot.netif.hwaddr", temp, 1); } if (intf_mtu != 0) { char mtu[16]; sprintf(mtu, "%u", intf_mtu); setenv("boot.netif.mtu", mtu, 1); } printf("pxe_open: server addr: %s\n", inet_ntoa(rootip)); printf("pxe_open: server path: %s\n", rootpath); printf("pxe_open: gateway ip: %s\n", inet_ntoa(gateip)); if (netproto == NET_NFS) { setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); setenv("boot.nfsroot.path", rootpath, 1); } else if (netproto == NET_TFTP) { setenv("boot.netif.server", inet_ntoa(rootip), 1); setenv("boot.tftproot.path", rootpath, 1); } setenv("dhcp.host-name", hostname, 1); setenv("pxeboot.ip", inet_ntoa(myip), 1); if (bootplayer.Hardware == ETHER_TYPE) { sprintf(temp, "%6D", bootplayer.CAddr, ":"); setenv("pxeboot.hwaddr", temp, 1); } } } pxe_opens++; f->f_devdata = &pxe_sock; return (error); } static int pxe_close(struct open_file *f) { #ifdef PXE_DEBUG if (pxe_debug) printf("pxe_close: opens=%d\n", pxe_opens); #endif /* On last close, do netif close, etc. */ f->f_devdata = NULL; /* Extra close call? */ if (pxe_opens <= 0) return (0); pxe_opens--; /* Not last close? */ if (pxe_opens > 0) return(0); if (netproto == NET_NFS) { /* get an NFS filehandle for our root filesystem */ pxe_setnfshandle(rootpath); } if (pxe_sock >= 0) { #ifdef PXE_DEBUG if (pxe_debug) printf("pxe_close: calling netif_close()\n"); #endif netif_close(pxe_sock); pxe_sock = -1; } return (0); } static void pxe_print(int verbose) { if (pxe_call == NULL) return; printf(" pxe0: %s:%s\n", inet_ntoa(rootip), rootpath); } static void pxe_cleanup(void) { #ifdef PXE_DEBUG t_PXENV_UNLOAD_STACK *unload_stack_p = (t_PXENV_UNLOAD_STACK *)scratch_buffer; t_PXENV_UNDI_SHUTDOWN *undi_shutdown_p = (t_PXENV_UNDI_SHUTDOWN *)scratch_buffer; #endif if (pxe_call == NULL) return; pxe_call(PXENV_UNDI_SHUTDOWN); #ifdef PXE_DEBUG if (pxe_debug && undi_shutdown_p->Status != 0) printf("pxe_cleanup: UNDI_SHUTDOWN failed %x\n", undi_shutdown_p->Status); #endif pxe_call(PXENV_UNLOAD_STACK); #ifdef PXE_DEBUG if (pxe_debug && unload_stack_p->Status != 0) printf("pxe_cleanup: UNLOAD_STACK failed %x\n", unload_stack_p->Status); #endif } void pxe_perror(int err) { return; } /* * Reach inside the libstand NFS code and dig out an NFS handle * for the root filesystem. */ #ifdef OLD_NFSV2 struct nfs_iodesc { struct iodesc *iodesc; off_t off; u_char fh[NFS_FHSIZE]; /* structure truncated here */ }; extern struct nfs_iodesc nfs_root_node; extern int rpc_port; static void pxe_rpcmountcall() { struct iodesc *d; int error; if (!(d = socktodesc(pxe_sock))) return; d->myport = htons(--rpc_port); d->destip = rootip; if ((error = nfs_getrootfh(d, rootpath, nfs_root_node.fh)) != 0) printf("NFS MOUNT RPC error: %d\n", error); nfs_root_node.iodesc = d; } static void pxe_setnfshandle(char *rootpath) { int i; u_char *fh; char buf[2 * NFS_FHSIZE + 3], *cp; /* * If NFS files were never opened, we need to do mount call * ourselves. Use nfs_root_node.iodesc as flag indicating * previous NFS usage. */ if (nfs_root_node.iodesc == NULL) pxe_rpcmountcall(); fh = &nfs_root_node.fh[0]; buf[0] = 'X'; cp = &buf[1]; for (i = 0; i < NFS_FHSIZE; i++, cp += 2) sprintf(cp, "%02x", fh[i]); sprintf(cp, "X"); setenv("boot.nfsroot.nfshandle", buf, 1); } #else /* !OLD_NFSV2 */ #define NFS_V3MAXFHSIZE 64 struct nfs_iodesc { struct iodesc *iodesc; off_t off; uint32_t fhsize; u_char fh[NFS_V3MAXFHSIZE]; /* structure truncated */ }; extern struct nfs_iodesc nfs_root_node; extern int rpc_port; static void pxe_rpcmountcall() { struct iodesc *d; int error; if (!(d = socktodesc(pxe_sock))) return; d->myport = htons(--rpc_port); d->destip = rootip; if ((error = nfs_getrootfh(d, rootpath, &nfs_root_node.fhsize, nfs_root_node.fh)) != 0) { printf("NFS MOUNT RPC error: %d\n", error); nfs_root_node.fhsize = 0; } nfs_root_node.iodesc = d; } static void pxe_setnfshandle(char *rootpath) { int i; u_char *fh; char buf[2 * NFS_V3MAXFHSIZE + 3], *cp; /* * If NFS files were never opened, we need to do mount call * ourselves. Use nfs_root_node.iodesc as flag indicating * previous NFS usage. */ if (nfs_root_node.iodesc == NULL) pxe_rpcmountcall(); fh = &nfs_root_node.fh[0]; buf[0] = 'X'; cp = &buf[1]; for (i = 0; i < nfs_root_node.fhsize; i++, cp += 2) sprintf(cp, "%02x", fh[i]); sprintf(cp, "X"); setenv("boot.nfsroot.nfshandle", buf, 1); sprintf(buf, "%d", nfs_root_node.fhsize); setenv("boot.nfsroot.nfshandlelen", buf, 1); } #endif /* OLD_NFSV2 */ void pxenv_call(int func) { #ifdef PXE_DEBUG if (pxe_debug) printf("pxenv_call %x\n", func); #endif bzero(&v86, sizeof(v86)); bzero(data_buffer, sizeof(data_buffer)); __pxenvseg = pxenv_p->RMEntry.segment; __pxenvoff = pxenv_p->RMEntry.offset; v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; v86.es = VTOPSEG(scratch_buffer); v86.edi = VTOPOFF(scratch_buffer); v86.addr = (VTOPSEG(__pxenventry) << 16) | VTOPOFF(__pxenventry); v86.ebx = func; v86int(); v86.ctl = V86_FLAGS; } void bangpxe_call(int func) { #ifdef PXE_DEBUG if (pxe_debug) printf("bangpxe_call %x\n", func); #endif bzero(&v86, sizeof(v86)); bzero(data_buffer, sizeof(data_buffer)); __bangpxeseg = pxe_p->EntryPointSP.segment; __bangpxeoff = pxe_p->EntryPointSP.offset; v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; v86.edx = VTOPSEG(scratch_buffer); v86.eax = VTOPOFF(scratch_buffer); v86.addr = (VTOPSEG(__bangpxeentry) << 16) | VTOPOFF(__bangpxeentry); v86.ebx = func; v86int(); v86.ctl = V86_FLAGS; } time_t -getsecs() +getsecs(void) { time_t n = 0; time(&n); return n; } static int pxe_netif_match(struct netif *nif, void *machdep_hint) { return 1; } static int pxe_netif_probe(struct netif *nif, void *machdep_hint) { t_PXENV_UDP_OPEN *udpopen_p = (t_PXENV_UDP_OPEN *)scratch_buffer; if (pxe_call == NULL) return -1; bzero(udpopen_p, sizeof(*udpopen_p)); udpopen_p->src_ip = bootplayer.yip; pxe_call(PXENV_UDP_OPEN); if (udpopen_p->status != 0) { printf("pxe_netif_probe: failed %x\n", udpopen_p->status); return -1; } return 0; } static void pxe_netif_end(struct netif *nif) { t_PXENV_UDP_CLOSE *udpclose_p = (t_PXENV_UDP_CLOSE *)scratch_buffer; bzero(udpclose_p, sizeof(*udpclose_p)); pxe_call(PXENV_UDP_CLOSE); if (udpclose_p->status != 0) printf("pxe_end failed %x\n", udpclose_p->status); } static void pxe_netif_init(struct iodesc *desc, void *machdep_hint) { int i; for (i = 0; i < 6; ++i) desc->myea[i] = bootplayer.CAddr[i]; desc->xid = bootplayer.ident; } static int pxe_netif_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) { return len; } static int pxe_netif_put(struct iodesc *desc, void *pkt, size_t len) { return len; } ssize_t sendudp(struct iodesc *h, void *pkt, size_t len) { t_PXENV_UDP_WRITE *udpwrite_p = (t_PXENV_UDP_WRITE *)scratch_buffer; bzero(udpwrite_p, sizeof(*udpwrite_p)); udpwrite_p->ip = h->destip.s_addr; udpwrite_p->dst_port = h->destport; udpwrite_p->src_port = h->myport; udpwrite_p->buffer_size = len; udpwrite_p->buffer.segment = VTOPSEG(pkt); udpwrite_p->buffer.offset = VTOPOFF(pkt); if (netmask == 0 || SAMENET(myip, h->destip, netmask)) udpwrite_p->gw = 0; else udpwrite_p->gw = gateip.s_addr; pxe_call(PXENV_UDP_WRITE); #if 0 /* XXX - I dont know why we need this. */ delay(1000); #endif if (udpwrite_p->status != 0) { /* XXX: This happens a lot. It shouldn't. */ if (udpwrite_p->status != 1) printf("sendudp failed %x\n", udpwrite_p->status); return -1; } return len; } ssize_t readudp(struct iodesc *h, void *pkt, size_t len, time_t timeout) { t_PXENV_UDP_READ *udpread_p = (t_PXENV_UDP_READ *)scratch_buffer; struct udphdr *uh = NULL; uh = (struct udphdr *) pkt - 1; bzero(udpread_p, sizeof(*udpread_p)); udpread_p->dest_ip = h->myip.s_addr; udpread_p->d_port = h->myport; udpread_p->buffer_size = len; udpread_p->buffer.segment = VTOPSEG(data_buffer); udpread_p->buffer.offset = VTOPOFF(data_buffer); pxe_call(PXENV_UDP_READ); #if 0 /* XXX - I dont know why we need this. */ delay(1000); #endif if (udpread_p->status != 0) { /* XXX: This happens a lot. It shouldn't. */ if (udpread_p->status != 1) printf("readudp failed %x\n", udpread_p->status); return -1; } bcopy(data_buffer, pkt, udpread_p->buffer_size); uh->uh_sport = udpread_p->s_port; return udpread_p->buffer_size; } Index: head/sys/boot/ofw/libofw/ofw_time.c =================================================================== --- head/sys/boot/ofw/libofw/ofw_time.c (revision 306158) +++ head/sys/boot/ofw/libofw/ofw_time.c (revision 306159) @@ -1,61 +1,61 @@ /*- * Copyright (c) 2000 Benno Rice * 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 Benno Rice ``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 REGENTS 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. */ #include __FBSDID("$FreeBSD$"); #include #include "openfirm.h" time_t time(time_t *tloc) { int secs; secs = OF_milliseconds() / 1000; if (tloc) *tloc = secs; return secs; } -int -getsecs() +time_t +getsecs(void) { time_t n = 0; time(&n); return n; } void delay(int usecs) { int msecs, start; msecs = usecs / 1000; start = OF_milliseconds(); while (OF_milliseconds() - start < msecs); } Index: head/sys/boot/powerpc/kboot/main.c =================================================================== --- head/sys/boot/powerpc/kboot/main.c (revision 306158) +++ head/sys/boot/powerpc/kboot/main.c (revision 306159) @@ -1,324 +1,324 @@ /*- * Copyright (C) 2010-2014 Nathan Whitehorn * 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 ``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 TOOLS GMBH 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #define _KERNEL #include #include "bootstrap.h" #include "host_syscall.h" struct arch_switch archsw; extern void *_end; extern char bootprog_name[]; extern char bootprog_rev[]; extern char bootprog_date[]; extern char bootprog_maker[]; int kboot_getdev(void **vdev, const char *devspec, const char **path); ssize_t kboot_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t kboot_copyout(vm_offset_t src, void *dest, const size_t len); ssize_t kboot_readin(const int fd, vm_offset_t dest, const size_t len); int kboot_autoload(void); uint64_t kboot_loadaddr(u_int type, void *data, uint64_t addr); int kboot_setcurrdev(struct env_var *ev, int flags, const void *value); extern int command_fdt_internal(int argc, char *argv[]); int kboot_getdev(void **vdev, const char *devspec, const char **path) { int i; const char *devpath, *filepath; struct devsw *dv; struct devdesc *desc; if (strchr(devspec, ':') != NULL) { devpath = devspec; filepath = strchr(devspec, ':') + 1; } else { devpath = getenv("currdev"); filepath = devspec; } for (i = 0; (dv = devsw[i]) != NULL; i++) { if (strncmp(dv->dv_name, devpath, strlen(dv->dv_name)) == 0) goto found; } return (ENOENT); found: if (path != NULL && filepath != NULL) *path = filepath; else if (path != NULL) *path = strchr(devspec, ':') + 1; if (vdev != NULL) { desc = malloc(sizeof(*desc)); desc->d_dev = dv; desc->d_unit = 0; desc->d_opendata = strdup(devpath); *vdev = desc; } return (0); } int main(int argc, const char **argv) { void *heapbase; const size_t heapsize = 15*1024*1024; const char *bootdev = argv[1]; /* * Set the heap to one page after the end of the loader. */ heapbase = host_getmem(heapsize); setheap(heapbase, heapbase + heapsize); /* * Set up console. */ cons_probe(); printf("Boot device: %s\n", bootdev); archsw.arch_getdev = kboot_getdev; archsw.arch_copyin = kboot_copyin; archsw.arch_copyout = kboot_copyout; archsw.arch_readin = kboot_readin; archsw.arch_autoload = kboot_autoload; archsw.arch_loadaddr = kboot_loadaddr; printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); setenv("currdev", bootdev, 1); setenv("loaddev", bootdev, 1); setenv("LINES", "24", 1); interact(NULL); /* doesn't return */ return (0); } void exit(int code) { /* XXX: host_exit */ } void delay(int usecs) { struct host_timeval tvi, tv; uint64_t ti, t; host_gettimeofday(&tvi, NULL); ti = tvi.tv_sec*1000000 + tvi.tv_usec; do { host_gettimeofday(&tv, NULL); t = tv.tv_sec*1000000 + tv.tv_usec; } while (t < ti + usecs); } -int -getsecs() +time_t +getsecs(void) { struct host_timeval tv; host_gettimeofday(&tv, NULL); return (tv.tv_sec); } time_t time(time_t *tloc) { time_t rv; rv = getsecs(); if (tloc != NULL) *tloc = rv; return (rv); } struct kexec_segment { void *buf; int bufsz; void *mem; int memsz; }; struct kexec_segment loaded_segments[128]; int nkexec_segments = 0; static ssize_t get_phys_buffer(vm_offset_t dest, const size_t len, void **buf) { int i = 0; const size_t segsize = 2*1024*1024; for (i = 0; i < nkexec_segments; i++) { if (dest >= (vm_offset_t)loaded_segments[i].mem && dest < (vm_offset_t)loaded_segments[i].mem + loaded_segments[i].memsz) goto out; } loaded_segments[nkexec_segments].buf = host_getmem(segsize); loaded_segments[nkexec_segments].bufsz = segsize; loaded_segments[nkexec_segments].mem = (void *)rounddown2(dest,segsize); loaded_segments[nkexec_segments].memsz = segsize; i = nkexec_segments; nkexec_segments++; out: *buf = loaded_segments[i].buf + (dest - (vm_offset_t)loaded_segments[i].mem); return (min(len,loaded_segments[i].bufsz - (dest - (vm_offset_t)loaded_segments[i].mem))); } ssize_t kboot_copyin(const void *src, vm_offset_t dest, const size_t len) { ssize_t segsize, remainder; void *destbuf; remainder = len; do { segsize = get_phys_buffer(dest, remainder, &destbuf); bcopy(src, destbuf, segsize); remainder -= segsize; src += segsize; dest += segsize; } while (remainder > 0); return (len); } ssize_t kboot_copyout(vm_offset_t src, void *dest, const size_t len) { ssize_t segsize, remainder; void *srcbuf; remainder = len; do { segsize = get_phys_buffer(src, remainder, &srcbuf); bcopy(srcbuf, dest, segsize); remainder -= segsize; src += segsize; dest += segsize; } while (remainder > 0); return (len); } ssize_t kboot_readin(const int fd, vm_offset_t dest, const size_t len) { void *buf; size_t resid, chunk, get; ssize_t got; vm_offset_t p; p = dest; chunk = min(PAGE_SIZE, len); buf = malloc(chunk); if (buf == NULL) { printf("kboot_readin: buf malloc failed\n"); return (0); } for (resid = len; resid > 0; resid -= got, p += got) { get = min(chunk, resid); got = read(fd, buf, get); if (got <= 0) { if (got < 0) printf("kboot_readin: read failed\n"); break; } kboot_copyin(buf, p, got); } free (buf); return (len - resid); } int kboot_autoload(void) { return (0); } uint64_t kboot_loadaddr(u_int type, void *data, uint64_t addr) { /* * Need to stay out of the way of Linux. /chosen/linux,kernel-end does * a better job here, but use a fixed offset for now. */ if (type == LOAD_ELF) addr = roundup(addr, PAGE_SIZE); else addr += 64*1024*1024; /* Stay out of the way of Linux */ return (addr); } void _start(int argc, const char **argv, char **env) { register volatile void **sp asm("r1"); main((int)sp[0], (const char **)&sp[1]); } /* * Since proper fdt command handling function is defined in fdt_loader_cmd.c, * and declaring it as extern is in contradiction with COMMAND_SET() macro * (which uses static pointer), we're defining wrapper function, which * calls the proper fdt handling routine. */ static int command_fdt(int argc, char *argv[]) { return (command_fdt_internal(argc, argv)); } COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt); Index: head/sys/boot/powerpc/ps3/main.c =================================================================== --- head/sys/boot/powerpc/ps3/main.c (revision 306158) +++ head/sys/boot/powerpc/ps3/main.c (revision 306159) @@ -1,253 +1,253 @@ /*- * Copyright (C) 2010 Nathan Whitehorn * Copyright (C) 2011 glevand (geoffrey.levand@mail.ru) * 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 ``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 TOOLS GMBH 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. */ #include __FBSDID("$FreeBSD$"); #include #include #define _KERNEL #include #include "bootstrap.h" #include "lv1call.h" #include "ps3.h" #include "ps3devdesc.h" struct arch_switch archsw; extern void *_end; extern char bootprog_name[]; extern char bootprog_rev[]; extern char bootprog_date[]; extern char bootprog_maker[]; int ps3_getdev(void **vdev, const char *devspec, const char **path); ssize_t ps3_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t ps3_copyout(vm_offset_t src, void *dest, const size_t len); ssize_t ps3_readin(const int fd, vm_offset_t dest, const size_t len); int ps3_autoload(void); int ps3_setcurrdev(struct env_var *ev, int flags, const void *value); static uint64_t basetb; int main(void) { uint64_t maxmem = 0; void *heapbase; int i, err; struct ps3_devdesc currdev; struct open_file f; lv1_get_physmem(&maxmem); ps3mmu_init(maxmem); /* * Set up console. */ cons_probe(); /* * Set the heap to one page after the end of the loader. */ heapbase = (void *)(maxmem - 0x80000); setheap(heapbase, maxmem); /* * March through the device switch probing for things. */ for (i = 0; devsw[i] != NULL; i++) { if (devsw[i]->dv_init != NULL) { err = (devsw[i]->dv_init)(); if (err) { printf("\n%s: initialization failed err=%d\n", devsw[i]->dv_name, err); continue; } } currdev.d_dev = devsw[i]; currdev.d_type = currdev.d_dev->dv_type; if (strcmp(devsw[i]->dv_name, "cd") == 0) { f.f_devdata = &currdev; currdev.d_unit = 0; if (devsw[i]->dv_open(&f, &currdev) == 0) break; } if (strcmp(devsw[i]->dv_name, "disk") == 0) { f.f_devdata = &currdev; currdev.d_unit = 3; currdev.d_disk.pnum = 1; currdev.d_disk.ptype = PTYPE_GPT; if (devsw[i]->dv_open(&f, &currdev) == 0) break; } if (strcmp(devsw[i]->dv_name, "net") == 0) break; } if (devsw[i] == NULL) panic("No boot device found!"); else printf("Boot device: %s\n", devsw[i]->dv_name); /* * Get timebase at boot. */ basetb = mftb(); archsw.arch_getdev = ps3_getdev; archsw.arch_copyin = ps3_copyin; archsw.arch_copyout = ps3_copyout; archsw.arch_readin = ps3_readin; archsw.arch_autoload = ps3_autoload; printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); printf("Memory: %lldKB\n", maxmem / 1024); env_setenv("currdev", EV_VOLATILE, ps3_fmtdev(&currdev), ps3_setcurrdev, env_nounset); env_setenv("loaddev", EV_VOLATILE, ps3_fmtdev(&currdev), env_noset, env_nounset); setenv("LINES", "24", 1); setenv("hw.platform", "ps3", 1); interact(NULL); /* doesn't return */ return (0); } void ppc_exception(int code, vm_offset_t where, register_t msr) { mtmsr(PSL_IR | PSL_DR | PSL_RI); printf("Exception %x at %#lx!\n", code, where); printf("Rebooting in 5 seconds...\n"); delay(10000000); lv1_panic(1); } const u_int ns_per_tick = 12; void exit(int code) { lv1_panic(code); } void delay(int usecs) { uint64_t tb,ttb; tb = mftb(); ttb = tb + howmany(usecs * 1000, ns_per_tick); while (tb < ttb) tb = mftb(); } -int -getsecs() +time_t +getsecs(void) { - return ((mftb() - basetb)*ns_per_tick/1000000000); + return ((time_t)((mftb() - basetb)*ns_per_tick/1000000000)); } time_t time(time_t *tloc) { time_t rv; rv = getsecs(); if (tloc != NULL) *tloc = rv; return (rv); } ssize_t ps3_copyin(const void *src, vm_offset_t dest, const size_t len) { bcopy(src, (void *)dest, len); return (len); } ssize_t ps3_copyout(vm_offset_t src, void *dest, const size_t len) { bcopy((void *)src, dest, len); return (len); } ssize_t ps3_readin(const int fd, vm_offset_t dest, const size_t len) { void *buf; size_t resid, chunk, get; ssize_t got; vm_offset_t p; p = dest; chunk = min(PAGE_SIZE, len); buf = malloc(chunk); if (buf == NULL) { printf("ps3_readin: buf malloc failed\n"); return(0); } for (resid = len; resid > 0; resid -= got, p += got) { get = min(chunk, resid); got = read(fd, buf, get); if (got <= 0) { if (got < 0) printf("ps3_readin: read failed\n"); break; } bcopy(buf, (void *)p, got); } free(buf); return (len - resid); } int ps3_autoload(void) { return (0); } Index: head/sys/boot/uboot/lib/time.c =================================================================== --- head/sys/boot/uboot/lib/time.c (revision 306158) +++ head/sys/boot/uboot/lib/time.c (revision 306159) @@ -1,65 +1,65 @@ /*- * Copyright (c) 2000 Benno Rice * Copyright (c) 2007 Semihalf, Rafal Jaworowski * 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. */ #include __FBSDID("$FreeBSD$"); #include #include "glue.h" /* * Return the time in seconds since the beginning of the day. */ time_t time(time_t *tloc) { int secs; secs = ub_get_timer(0) / 1000; if (tloc) *tloc = secs; return (secs); } -int +time_t getsecs(void) { return (time(NULL)); } /* * Use U-Boot udelay() function to wait for a given microseconds period */ void delay(int usecs) { ub_udelay(usecs); }