2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 FILE_LICENCE ( GPL2_OR_LATER );
25 #include <ipxe/process.h>
26 #include <ipxe/console.h>
27 #include <ipxe/keys.h>
29 #include <ipxe/monojob.h>
30 #include <ipxe/timer.h>
34 * Single foreground job
38 static int monojob_rc;
40 static void monojob_close ( struct interface *intf, int rc ) {
42 intf_restart ( intf, rc );
45 static struct interface_operation monojob_intf_op[] = {
46 INTF_OP ( intf_close, struct interface *, monojob_close ),
49 static struct interface_descriptor monojob_intf_desc =
50 INTF_DESC_PURE ( monojob_intf_op );
52 struct interface monojob = INTF_INIT ( monojob_intf_desc );
55 * Wait for single foreground job to complete
57 * @v string Job description to display, or NULL to be silent
58 * @v timeout Timeout period, in ticks (0=indefinite)
59 * @ret rc Job final status code
61 int monojob_wait ( const char *string, unsigned long timeout ) {
62 struct job_progress progress;
63 unsigned long last_keycheck;
64 unsigned long last_progress;
65 unsigned long last_display;
67 unsigned long elapsed;
68 unsigned long completed = 0;
69 unsigned long scaled_completed;
70 unsigned long scaled_total;
71 unsigned int percentage;
72 int shown_percentage = 0;
78 printf ( "%s...", string );
79 monojob_rc = -EINPROGRESS;
80 last_keycheck = last_progress = last_display = currticks();
81 while ( monojob_rc == -EINPROGRESS ) {
83 /* Allow job to progress */
87 /* Check for keypresses. This can be time-consuming,
88 * so check only once per clock tick.
90 elapsed = ( now - last_keycheck );
94 if ( key == CTRL_C ) {
95 monojob_rc = -ECANCELED;
102 /* Monitor progress */
103 ongoing_rc = job_progress ( &monojob, &progress );
105 /* Reset timeout if progress has been made */
106 if ( completed != progress.completed )
108 completed = progress.completed;
110 /* Check for timeout, if applicable */
111 elapsed = ( now - last_progress );
112 if ( timeout && ( elapsed >= timeout ) ) {
113 monojob_rc = ( ongoing_rc ? ongoing_rc : -ETIMEDOUT );
117 /* Display progress, if applicable */
118 elapsed = ( now - last_display );
119 if ( string && ( elapsed >= TICKS_PER_SEC ) ) {
120 if ( shown_percentage )
121 printf ( "\b\b\b\b \b\b\b\b" );
122 /* Normalise progress figures to avoid overflow */
123 scaled_completed = ( progress.completed / 128 );
124 scaled_total = ( progress.total / 128 );
125 if ( scaled_total ) {
126 percentage = ( ( 100 * scaled_completed ) /
128 printf ( "%3d%%", percentage );
129 shown_percentage = 1;
132 shown_percentage = 0;
138 monojob_close ( &monojob, rc );
140 if ( shown_percentage )
141 printf ( "\b\b\b\b \b\b\b\b" );
145 printf ( " %s\n", strerror ( rc ) );