[PROJECT] HaRET on WP7

Search This thread

dcordes

Retired Senior Recognized Developer
Nov 20, 2007
707
254
Hi
* Please help keeping the noise level low: Don't ask for ETA (stuff will be anounced), use Thanks buttons to say thx, etc.
* This will work on "fully unlocked" WP7 devices only and is not limited to specific phones

thx, dcordes

HaRET (Handhelds Reverse Engineering Tool) has been used on smartphones and PDAs with previous WinCE (Windows Mobile) versions to

* boot the Linux kernel (=> use Linux based OS like Android)
* obtain information about hardware and software (=> reverse engineering) in order to accordingly modify the Linux kernel (drivers).

Famous HTC devices that are capable of running HaRET are the QSD8250 based HTC HD2 and a wide range of MSM7xxA based phones like the diamond, raphael and touch pro 2.

WP7 is and will be shipped on many devices with quality hardware. In order to be able to run Linux on these, a novel aim is to investigate the use of HaRET on WP7 based devices. WP7 is known to posess several mechanisms to prevent this.

A discussion about the problem has beend started on the official HaRET development mailing list by Jaxbot:
http://lists.linuxtogo.org/pipermail/haret-devel/2012-January/000150.html
You need to send a subscription mail in order to write to the list. The original creators of HaRET as well as many good developers with low level skills (from XDA: Cotulla, NetRipper, cr2) are subscribed to it but maybe not many of them have access to a WP7 device.

HaRET source code repository with history:
http://git.linuxtogo.org/?p=groups/haret/haret.git

Documentation of the HaRET project (publicly accessible wiki):
http://htc-linux.org/wiki/index.php?title=HaRET
See http://htc-linux.org/wiki/index.php?title=HaRET/Documentation#Development for how to compile.

We should discuss the technical possibilites and challenges (if any :cool:) about this project in this thread.

Update: Lots of insight has been gained. Since progress is rapid, uptades are not listed here yet. Please read the full thread for now.
 
Last edited:

egzthunder1

Admin Emeritus - Spirit of XDA
Hey dcordes,

I did a bit of housecleaning on this thread as I would hate to see this become your old Android-HD2 port thread :p

I want to see some real discussions going on in here (for a change).

So, HaRET must be, if memory serves me well, developed based on the processor, right? If it worked so well for the HD2, considering that most WP7+ devices from HTC also use Snapdragon's.... it should only take a few tweaks to get it to run (at least compatibility with HW) with most HTC WP7+ devices. The problems will be (I guess):

* Porting over from WM6.5 to WP7+ (may not be as bad as it sounds);
* Making sure that whatever this thing is coded with, it does not have interoplock code running on it (which I think will be kinda difficult considering that several apps that require access to less critical areas of the device require this). if it is interoplocked, then you will run into the issue of multiple versions out there (see Heathcliff's interopunlock thread to see/learn about the HTC variants on the new drivers, etc);
* Drivers, kernels, etc... but I believe that the HW specs between WP7+ devices and the HD2 are not so different, so you may even be able to get the same kernels to work with a few tweaks.

My Titan is already drooling with expectation :)


Please let me know if this thread needs further cleaning....

Good to see you back.
 

Jaxbot

Inactive Recognized Developer
Mar 14, 2009
1,224
548
windowsphonehacker.com
I feel somewhat obligated to make an appearance, then ;)

Here's what I know, on the WP7 side of things:
A lot of APIs were removed, but the core pieces of CE still remain. I don't know what HaRET does to load Linux into the memory, but I would be shocked if it wasn't possible.

Part of the APIs that were removed were GUI related. This is why HaRET segfaults when you try to load it on a full unlocked device. If these pieces were removed, making it rely only on the command line, the loader might actually work, more or less. A WP7 Silverlight app could easily be built to serve as a launcher for it.

Those pieces aside, it is basically the technical pieces that have yet to be dug into that we are bound to run into. Curious to see what will happen, glad to see this getting some attention ;) Cheers!
 

nikola360

Senior Member
Apr 10, 2008
115
18
for HD2 ok, but for other phone that hasn't SD card?..... i hope however Ubuntu 0.4 will go on magldr, right? :D
 

DJSave

Senior Member
Oct 27, 2011
315
123
Tbilisi
As the MAGLDR for Samsung focus/omnia7 will be out in around just now , maybe it will be possible to manage smthng :)
 

dcordes

Retired Senior Recognized Developer
Nov 20, 2007
707
254
nhathoa egzthunder1, thank you very much for the kind welcome :)

Here's what I know, on the WP7 side of things:
A lot of APIs were removed, but the core pieces of CE still remain. I don't know what HaRET does to load Linux into the memory, but I would be shocked if it wasn't possible.

Part of the APIs that were removed were GUI related. This is why HaRET segfaults when you try to load it on a full unlocked device. If these pieces were removed, making it rely only on the command line, the loader might actually work, more or less. A WP7 Silverlight app could easily be built to serve as a launcher for it.

Those pieces aside, it is basically the technical pieces that have yet to be dug into that we are bound to run into. Curious to see what will happen, glad to see this getting some attention ;) Cheers!

I don't have much insight on how the kernel is loaded either. Obviously it's important for HaRET to have a non-protected memory region it is allowed to write to and then there is something called trampoline that will flush remaining memory and execute the kernel...

GUI: http://htc-linux.org/wiki/index.php?title=HaRET_Documentation#HaRET_commands
"HaRET is fundamentally a command-line driven application."

Can you try to rename your default.txt into startup.txt ? In presence of startup.txt inside the directory of the exectuable, HaRET will automatically run commands inside that file, rather than first showing the GUI. (Maybe it will still crash cause it still depends on the libraries although they won't be used ? See linload below)

Also be sure to create a file named earlyharetlog.txt and check the resulting log in haretlog.txt which would be a good thing to put on the mailing list.

The other way to invoke HaRET commands is through haretconsole (also check doku above). Once the gui shows you can tap a listen button and haret will launch a telnet server. You can then connect remotly from your computer OR (and that might become our replacement gui :) from a local telnet client on the phone. There is one available in the wp7 software manager: http://www.windowsphone.com/en-GB/apps/333b1e98-4c72-4cf9-a5d0-9d82b6b18213

One possible way to cut through all GUI right now is the linload feature of haret that will burn loader, kernel, startup.txt and initrd into one single exe . Requires local source code and build environment to create. I think it is very likly that this will not depend on any GUI libs so we should really try in case of startup.txt failure!

Beside linload we might create a HaRET stripped from GUI that will be accessible via haretconsole only until we have a new WP7 compatible GUI.

Regarding compiling: http://htc-linux.org/wiki/index.php?title=HaRET_Documentation doesn't have anything on that. But the source code does: http://git.linuxtogo.org/?p=groups/haret/haret.git;a=tree;f=docs

for HD2 ok, but for other phone that hasn't SD card?..... i hope however Ubuntu 0.4 will go on magldr, right? :D
Doesn't matter, why would you need SD card ? I guess if a phone lacks SD, it will come with plenty internal storage that can hold at least a minimal rootfs of any Linux distro.

Yes HD2 Ubuntu will work with magldr, I already picked up the work with that but that's offtopic. I will anounce any news via hd2 ubuntu forum section and twitter.


EDIT: If somebody is willing to try, I can create a linload for HD2s that have WP7 flashed. This will be a perfect test setup because we have a known working Linux kernel for the HD2.
 
Last edited:

Jaxbot

Inactive Recognized Developer
Mar 14, 2009
1,224
548
windowsphonehacker.com
nhathoa egzthunder1, thank you very much for the kind welcome :)



I don't have much insight on how the kernel is loaded either. Obviously it's important for HaRET to have a non-protected memory region it is allowed to write to and then there is something called trampoline that will flush remaining memory and execute the kernel...

GUI: http://htc-linux.org/wiki/index.php?title=HaRET_Documentation#HaRET_commands
"HaRET is fundamentally a command-line driven application."

Can you try to rename your default.txt into startup.txt ? In presence of startup.txt inside the directory of the exectuable, HaRET will automatically run commands inside that file, rather than first showing the GUI. (Maybe it will still crash cause it still depends on the libraries although they won't be used ? See linload below)

Also be sure to create a file named earlyharetlog.txt and check the resulting log in haretlog.txt which would be a good thing to put on the mailing list.

The other way to invoke HaRET commands is through haretconsole (also check doku above). Once the gui shows you can tap a listen button and haret will launch a telnet server. You can then connect remotly from your computer OR (and that might become our replacement gui :) from a local telnet client on the phone. There is one available in the wp7 software manager: http://www.windowsphone.com/en-GB/apps/333b1e98-4c72-4cf9-a5d0-9d82b6b18213

One possible way to cut through all GUI right now is the linload feature of haret that will burn loader, kernel, startup.txt and initrd into one single exe . Requires local source code and build environment to create. I think it is very likly that this will not depend on any GUI libs so we should really try in case of startup.txt failure!

Beside linload we might create a HaRET stripped from GUI that will be accessible via haretconsole only until we have a new WP7 compatible GUI.

Regarding compiling: http://htc-linux.org/wiki/index.php?title=HaRET_Documentation doesn't have anything on that. But the source code does: http://git.linuxtogo.org/?p=groups/haret/haret.git;a=tree;f=docs


Doesn't matter, why would you need SD card ? I guess if a phone lacks SD, it will come with plenty internal storage that can hold at least a minimal rootfs of any Linux distro.

Yes HD2 Ubuntu will work with magldr, I already picked up the work with that but that's offtopic. I will anounce any news via hd2 ubuntu forum section and twitter.


EDIT: If somebody is willing to try, I can create a linload for HD2s that have WP7 flashed. This will be a perfect test setup because we have a known working Linux kernel for the HD2.

I've tried startup.txt, it still segfaults, won't even print out a log from what I can tell. I'll play around with some stuff and report back, though.
 

dcordes

Retired Senior Recognized Developer
Nov 20, 2007
707
254

Attachments

  • linload-hd2.zip
    5.2 MB · Views: 806
Last edited:
  • Like
Reactions: pirlano

majkeljj

Senior Member
Nov 28, 2007
527
14
i have a stupid question, what is reason test it on HD2 where you can install android without problem. on native wp7 phones you will not run this app as I know. or maybe I'm wrong? maybe on custom rom?
I have mozart interop unlocked, I can test something if there will be some staff for my phone.
 

dcordes

Retired Senior Recognized Developer
Nov 20, 2007
707
254
I'm going to test this mate
Thanks a lot. this is going to be interesting!
Could you create a file called earlyharetlog.txt inside the same directory of linload.exe ? I don't know if this works but see if it will give you a logfile in the same directory after starting linload.exe
I bet it will just crash, just like normal HaRET.exe when using startup.txt
 

Jaxbot

Inactive Recognized Developer
Mar 14, 2009
1,224
548
windowsphonehacker.com
Thanks a lot. this is going to be interesting!
Could you create a file called earlyharetlog.txt inside the same directory of linload.exe ? I don't know if this works but see if it will give you a logfile in the same directory after starting linload.exe
I bet it will just crash, just like normal HaRET.exe when using startup.txt

Tried it with earlyharetlog.txt in the same directory. No log is spit out, and while there is no error code when running the EXE, it crashes before I can even pull the running processes list.
 

dcordes

Retired Senior Recognized Developer
Nov 20, 2007
707
254
ok does it show anything ? loading screen or so ? it's what I expected. if you compiled haret.exe before, linload takes 2 seconds to build. It might just be the exact haret.exe ...
 

minDark

Member
Nov 15, 2007
16
6
Targoviste
From what I saw, linload.exe cannot run under WP7 because it depends on libgcc_s_sjlj-1.dll, witch cannot be found in WP7. You can try running Haret.exe. All the necessary APIs are there, so no problem about UI related functions. Only one function is missing: SetKmode, witch is used by Haret to take kernel mode privileges, to flush the memory. In WP7 this function is not available and i don't know any workaround about this. We can try to recompile Haret from source, remove SetKmode call from output.cpp and memory.cpp, update functions ordinals in the import table for new Haret.exe to match those from WP7 coredll.dll (i'm not sure about this, maybe can work without matching ordinals) and see if we have a working GUI.
 

dcordes

Retired Senior Recognized Developer
Nov 20, 2007
707
254
Thanks for this insight, minDark. may I ask how you found out about the missing dependencies?
It's not so nice that the kernel mode function is missing in WP7. How are we going to start the kernel without it?
I did as you proposed and compiled haret.exe without it. I just commented out lines containing setkmode. But I didn't change the ordinals stuff because I have no idea what that is.

no-kmode haret.exe with minDark's proposed kmode patch is attached. Any WP7 device owners welcome to test.

diff to current haret.git HEAD:
Code:
haret$ git diff
diff --git a/src/memory.cpp b/src/memory.cpp
index ccba659..53c0826 100644
--- a/src/memory.cpp
+++ b/src/memory.cpp
@@ -320,7 +320,7 @@ err:  VirtualFree (pmWindow, 0, MEM_RELEASE);
   if (slot >= PHYS_CACHE_COUNT)
   {
     // Go into supervisor mode
-    SetKMode (TRUE);
+//    SetKMode (TRUE);
     cli ();
     cpuFlushCache ();
 
@@ -333,7 +333,7 @@ err:  VirtualFree (pmWindow, 0, MEM_RELEASE);
 
     // Back to user mode
     sti ();
-    SetKMode (FALSE);
+//    SetKMode (FALSE);
   }
 
   // Move least recently used slot to front
@@ -354,12 +354,12 @@ void memPhysReset ()
   if (pmInited)
   {
     // Go into supervisor mode
-    SetKMode (TRUE);
+//    SetKMode (TRUE);
     cpuFlushCache ();
     // Restore the page table entries
     for (int i = 0; i < 16 * PHYS_CACHE_COUNT; i++)
       pmPT [i] = pmOldPT [i];
-    SetKMode (FALSE);
+//    SetKMode (FALSE);
 
     VirtualFree (pmL2PT, 0, MEM_RELEASE);
     VirtualFree (pmWindow, 0, MEM_RELEASE);
diff --git a/src/wince/output.cpp b/src/wince/output.cpp
index cc65d40..e4be7ed 100644
--- a/src/wince/output.cpp
+++ b/src/wince/output.cpp
@@ -276,9 +276,9 @@ prepThread()
     // All wince 3.0 and later machines are automatically in "kernel
     // mode".  We enable kernel mode by default to make older PDAs
     // (ce2.x) work.
-    Output("Setting KMode to true.");
-    int kmode = SetKMode(TRUE);
-    Output("Old KMode was %d", kmode);
+//    Output("Setting KMode to true.");
+//    int kmode = SetKMode(TRUE);
+//    Output("Old KMode was %d", kmode);
 }
 
 // Initialize the haret application.
 

Attachments

  • haret-nokmode.zip
    68.1 KB · Views: 423
Last edited:
  • Like
Reactions: pirlano

Ttblondey

Senior Member
Jan 1, 2008
1,690
103
I download it through my hd7 but when I try to open it stated this file isn't safe to open in your windows phone.
 

Top Liked Posts

  • There are no posts matching your filters.
  • 80
    Hi
    * Please help keeping the noise level low: Don't ask for ETA (stuff will be anounced), use Thanks buttons to say thx, etc.
    * This will work on "fully unlocked" WP7 devices only and is not limited to specific phones

    thx, dcordes

    HaRET (Handhelds Reverse Engineering Tool) has been used on smartphones and PDAs with previous WinCE (Windows Mobile) versions to

    * boot the Linux kernel (=> use Linux based OS like Android)
    * obtain information about hardware and software (=> reverse engineering) in order to accordingly modify the Linux kernel (drivers).

    Famous HTC devices that are capable of running HaRET are the QSD8250 based HTC HD2 and a wide range of MSM7xxA based phones like the diamond, raphael and touch pro 2.

    WP7 is and will be shipped on many devices with quality hardware. In order to be able to run Linux on these, a novel aim is to investigate the use of HaRET on WP7 based devices. WP7 is known to posess several mechanisms to prevent this.

    A discussion about the problem has beend started on the official HaRET development mailing list by Jaxbot:
    http://lists.linuxtogo.org/pipermail/haret-devel/2012-January/000150.html
    You need to send a subscription mail in order to write to the list. The original creators of HaRET as well as many good developers with low level skills (from XDA: Cotulla, NetRipper, cr2) are subscribed to it but maybe not many of them have access to a WP7 device.

    HaRET source code repository with history:
    http://git.linuxtogo.org/?p=groups/haret/haret.git

    Documentation of the HaRET project (publicly accessible wiki):
    http://htc-linux.org/wiki/index.php?title=HaRET
    See http://htc-linux.org/wiki/index.php?title=HaRET/Documentation#Development for how to compile.

    We should discuss the technical possibilites and challenges (if any :cool:) about this project in this thread.

    Update: Lots of insight has been gained. Since progress is rapid, uptades are not listed here yet. Please read the full thread for now.
    8
    Delay

    Sorry for delay. I have got unused phone from last HaRET using, then I made:

    1. Full internal memory cleaning.
    2. SD card changing to 32GB class 10 (I can recommend it for everybody). One screw was lying on the table after the repair and I do not know where it belongs :).
    3. Data restoring (big thanks to Ultrashot).
    4. Actualisations (unfortunately, Microsoft is lying again, the phone with 8860+8862 updates under LockScreen very quickly discharged too, all livetiles closing helps only). I hope we will have WM6, Ubuntu or RT on our WP7 devices in near future. My very old S80 devices knew how much more and lasted a week on a single charge.
    5. Finishing WP7 native FTP Client library, you are welcome for testing.

    Next weak I have very much work in a occupation, but I hope I will send to Jessenic much HaRET updates next weakend.
    8
    VS

    Now I have got HaRET incremental version working under Visual Studio 2008. It is compiled by cygwin/make, deployed to device and started under debugger, all from VS IDE. All output (Warning, Information, Error) is redirected to VS Output window. For example now (instead MessageBox):
    ...
    KMD1: 0xD9456944 $device\KMD1 Drivers\BuiltIn\KMDriver $bus\KMD1
    ListRunningDrivers(KMD1:) returns HANDLE 0xD9456944
    Load module: toolhelp.dll
    WP7RunInKernelMode(kmodedll.dll, KGetProcInfo, 0x39F248, 1, 0x39F274, 576, 0x39F180, 198)
    DeviceIoControl returns 1
    Error: 'Haret is not running in 'system' mode. Major functionality will not be present.'
    Load module: WindowTreeUpdater.dll
    ...
    WP7VirtualAlloc, WP7VirtualFree, WP7VirtualCopy is used instead VirtualAlloc, VirtualFree, VirtualCopy. But, by error message, I mean a big part of cpu.cpp module must be tranfered to kmode_dll.cpp.

    PHP:
    // Get Program Status Register value
    static inline uint32 cpuGetPSR(void) {
        uint32 val;
        asm volatile("mrs %0, cpsr" : "=r" (val));
        return val;
    }
    
    unsigned long KcpuGetPSR(unsigned char * InStructurePointer,
    		unsigned long InStructureLength, unsigned char * OutStructurePointer,
    		unsigned long OutStructureLength) {
    
    	TRACE_SAVE(L"KcpuGetPSR(0x%X, %d, 0x%X, %d)\n", InStructurePointer,
    			InStructureLength, OutStructurePointer, OutStructureLength);
    
    	if (OutStructurePointer && sizeof(uint32) == OutStructureLength) 
    	{
    		uint32 * pRes = (uint32 *) OutStructurePointer;
    
    		*pRes = cpuGetPSR();
    
    		TRACE_SAVE(L"cpuGetPSR() returns 0x%X\n", *pRes);
    
    		return ERROR_SUCCESS;
    	}
    	return ERROR_INVALID_PARAMETER;
    }

    After it:
    ...
    KMD1: 0xD9456944 $device\KMD1 Drivers\BuiltIn\KMDriver $bus\KMD1
    ListRunningDrivers(KMD1:) returns HANDLE 0xD9456944
    Load module: toolhelp.dll
    WP7RunInKernelMode(kmodedll.dll, KGetProcInfo, 0x21EF248, 1, 0x21EF274, 576, 0x21EF180, 198)
    DeviceIoControl returns 1
    WP7RunInKernelMode(kmodedll.dll, KcpuGetPSR, 0x21EF378, 1, 0x21EF374, 4, 0x21EF2AC, 198)
    DeviceIoControl returns 1
    Load module: WindowTreeUpdater.dll
    ...


    KGetProcInfo(0x21F1CE4, 1, 0x21F1F00, 576)
    pinfo filled, GetProcInfo returns ERROR_SUCCESS
    wVersion = 1
    szProcessCore = Snapdragon
    wCoreRevision = 0
    szProcessorName = QSD8250
    wProcessorRevision = 0
    szCatalogNumber =
    szVendor = QUALCOMM
    dwInstructionSet = 0
    dwClockSpeed = 998
    KcpuGetPSR(0x21F5CE4, 1, 0x21F5F00, 4)
    cpuGetPSR() returns 0x2000011F

    KMD_Open
    KMD_Open
    KMD_IoControl entry, dwCode=9
    KMD_IoControl WP7_DLL_CALL, dwCode=9
    Function kmodedll.dll::KGetProcInfo returns 0
    KMD_IoControl returned 1
    KMD_IoControl entry, dwCode=6
    KMD_IoControl IOCTL_WP7_ALLOC_ADDRESS, dwCode=6
    Function VirtualAllocEx(0x42,0x0,65536,0x2000,0x1) returns D97A0000
    KMD_IoControl returned 1
    KMD_IoControl entry, dwCode=8
    KMD_IoControl IOCTL_WP7_COPY_ADDRESS, dwCode=8
    Function VirtualCopy(0xD97A0000,0xAC0000,65536,0x604) returns 1
    KMD_IoControl returned 1
    KMD_IoControl entry, dwCode=6
    KMD_IoControl IOCTL_WP7_ALLOC_ADDRESS, dwCode=6
    Function VirtualAllocEx(0x42,0x0,65536,0x2000,0x1) returns D9EE0000
    KMD_IoControl returned 1
    KMD_IoControl entry, dwCode=8
    KMD_IoControl IOCTL_WP7_COPY_ADDRESS, dwCode=8
    Function VirtualCopy(0xD9EE0000,0xA90000,65536,0x604) returns 1
    KMD_IoControl returned 1
    KMD_IoControl entry, dwCode=6
    KMD_IoControl IOCTL_WP7_ALLOC_ADDRESS, dwCode=6
    Function VirtualAllocEx(0x42,0x0,65536,0x2000,0x1) returns DA020000
    KMD_IoControl returned 1
    KMD_IoControl entry, dwCode=8
    KMD_IoControl IOCTL_WP7_COPY_ADDRESS, dwCode=8
    Function VirtualCopy(0xDA020000,0xA91000,65536,0x604) returns 1
    KMD_IoControl returned 1
    KMD_IoControl entry, dwCode=9
    KMD_IoControl WP7_DLL_CALL, dwCode=9
    Function kmodedll.dll::KcpuGetPSR returns 0
    KMD_IoControl returned 1


    Function kmodedll.dll::KFunctionName returns 0 means SUCCESS (nonzero is Error code),
    in other attempts nonzero means OK (zero is FALSE or 0 bytes).

    Console works for me now:
    NLEDSET 0 1 // Start vibration
    NLEDSET 0 0 // Stop vibration
    But very much directives must be reimplemented to driver calling still.


    Better way, then functions redefining by one, will DEF_GETCPR and DEF_SETCPR macros adjustment to kernel driver using.

    I tried to port PocketPutty for WM to communicate on WP7 device. But, Putty.exe not goes to WinMain function. Do you know anybody, why entrypoint may not be called? It is probably by missing linked dll or function in WP7.

    I tried also to connect from Silverlight Telnet client to second device with HaRET and WiFi internet tethering running. But, message is "he remote host is actively refusing a connection" on related IP (192.168.33.1) and all ports (not only 9999). Do you know anybody, if Telnet is theoretically available by WiFi tethered connection?
    8
    Thread Cleaned

    Please only post if you have something to contribute. Also please avoid posting thank you we have a "thanks" button for that.

    Stop with the ETA posts, it just annoys the good developers. Just be grateful for the work they do!​
    8
    does this work with devices unlocked with wp7 root tools??if yes, i will be always ready to test it on my omnia w..

    Prahlad

    Yes, I have got HaRET last version running in the Kernel mode with full hardware and physical memory access too. Any unlock needed. But, my HTC7Pro needed hard reset after this version using to unbrick, then I mean it is too danger when you like your phone. Only one function was succesfully tested before HR - Vibration On/Off low-level switching. I have idea to make HaRET safe equivalent, but the way needs to finish my other related projects and I am too busy now. No C++ coder here wants my unfinished codes? Especially shell/batch interpreter with registry export/import/backup and new directives simply adding (may be used for own macro language definition too), pipes for easy interprocess comunication (unmanged/managed too), native WP7 installer with plugins system and low-level system scheduler projects are near of finishing. Any C++ student with free time can finish it all relatively quickly.