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
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL
);
29 #include <ipxe/process.h>
30 #include <ipxe/console.h>
31 #include <ipxe/keys.h>
33 #include <ipxe/monojob.h>
34 #include <ipxe/timer.h>
38 * Single foreground job
42 static int monojob_rc
;
44 static void monojob_close ( struct interface
*intf
, int rc
) {
46 intf_restart ( intf
, rc
);
49 static struct interface_operation monojob_intf_op
[] = {
50 INTF_OP ( intf_close
, struct interface
*, monojob_close
),
53 static struct interface_descriptor monojob_intf_desc
=
54 INTF_DESC_PURE ( monojob_intf_op
);
56 struct interface monojob
= INTF_INIT ( monojob_intf_desc
);
59 * Wait for single foreground job to complete
61 * @v string Job description to display, or NULL to be silent
62 * @v timeout Timeout period, in ticks (0=indefinite)
63 * @ret rc Job final status code
65 int monojob_wait ( const char *string
, unsigned long timeout
) {
66 struct job_progress progress
;
67 unsigned long last_keycheck
;
68 unsigned long last_progress
;
69 unsigned long last_display
;
71 unsigned long elapsed
;
72 unsigned long completed
= 0;
73 unsigned long scaled_completed
;
74 unsigned long scaled_total
;
75 unsigned int percentage
;
76 int shown_percentage
= 0;
82 printf ( "%s...", string
);
83 monojob_rc
= -EINPROGRESS
;
84 last_keycheck
= last_progress
= last_display
= currticks();
85 while ( monojob_rc
== -EINPROGRESS
) {
87 /* Allow job to progress */
91 /* Check for keypresses. This can be time-consuming,
92 * so check only once per clock tick.
94 elapsed
= ( now
- last_keycheck
);
98 if ( key
== CTRL_C
) {
99 monojob_rc
= -ECANCELED
;
106 /* Monitor progress */
107 ongoing_rc
= job_progress ( &monojob
, &progress
);
109 /* Reset timeout if progress has been made */
110 if ( completed
!= progress
.completed
)
112 completed
= progress
.completed
;
114 /* Check for timeout, if applicable */
115 elapsed
= ( now
- last_progress
);
116 if ( timeout
&& ( elapsed
>= timeout
) ) {
117 monojob_rc
= ( ongoing_rc ? ongoing_rc
: -ETIMEDOUT
);
121 /* Display progress, if applicable */
122 elapsed
= ( now
- last_display
);
123 if ( string
&& ( elapsed
>= TICKS_PER_SEC
) ) {
124 if ( shown_percentage
)
125 printf ( "\b\b\b\b \b\b\b\b" );
126 /* Normalise progress figures to avoid overflow */
127 scaled_completed
= ( progress
.completed
/ 128 );
128 scaled_total
= ( progress
.total
/ 128 );
129 if ( scaled_total
) {
130 percentage
= ( ( 100 * scaled_completed
) /
132 printf ( "%3d%%", percentage
);
133 shown_percentage
= 1;
136 shown_percentage
= 0;
142 monojob_close ( &monojob
, rc
);
144 if ( shown_percentage
)
145 printf ( "\b\b\b\b \b\b\b\b" );
149 printf ( " %s\n", strerror ( rc
) );