diff --git a/Final/log.txt b/Final/log.txt new file mode 100644 index 000000000..fb962d384 --- /dev/null +++ b/Final/log.txt @@ -0,0 +1,6963 @@ +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=used [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used * +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=free +lba_idx = 23 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=used [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=used [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=free [31]=stale [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used *[37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +lba_idx = 33 is valid +lba_idx = 34 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=free [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=used *[39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used *[47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +lba_idx = 36 is valid +lba_idx = 37 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=free [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=free [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=free [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=free [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=used +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used *[128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=used +lba_idx = 24 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=used +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used *[129]=used +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used *[118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=used +lba_idx = 23 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=free +[1]=used [11]=used [21]=stale [31]=used [41]=used [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=free +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=free +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=free +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=free +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=free +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=free +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=free +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=free +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used * +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=free +lba_idx = 32 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used *[38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +lba_idx = 37 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used *[47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 27 is valid +lba_idx = 28 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used *[117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +lba_idx = 33 is valid +lba_idx = 31 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=free [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=free [129]=used +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used *[126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=free [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=stale +lba_idx = 41 is valid +lba_idx = 20 is valid +lba_idx = 21 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=free +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=free +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=free +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=free +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=free +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=free +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=free +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=free +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used * +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=free +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=free +lba_idx = 35 is valid +lba_idx = 36 is valid +lba_idx = 37 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used *[36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used +lba_idx = 40 is valid +lba_idx = 29 is valid +lba_idx = 28 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=used +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used *[116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=used +lba_idx = 41 is valid +lba_idx = 20 is valid +lba_idx = 21 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=free [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=free [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=free [129]=used +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used *[127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=used +lba_idx = 33 is valid +lba_idx = 35 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used *[38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +lba_idx = 27 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=free +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=free +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=free +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=free +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=free +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=free +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=free +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=free +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used * +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=free +lba_idx = 22 is valid +lba_idx = 23 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used * +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used * +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used *[47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +lba_idx = 38 is valid +lba_idx = 39 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used *[37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 32 is valid +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used *[116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +lba_idx = 33 is valid +lba_idx = 38 is valid +lba_idx = 39 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used *[46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +lba_idx = 24 is valid +lba_idx = 25 is valid +lba_idx = 40 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=free [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=free [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=free [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=free [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=used +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used *[127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=stale +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=stale +lba_idx = 34 is valid +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=stale +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used *[37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=stale +lba_idx = 33 is valid +lba_idx = 39 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=stale +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used *[117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=stale +lba_idx = 26 is valid +lba_idx = 27 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=free +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=free +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=free +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=free +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=free +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=free +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=free +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used * +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=free +lba_idx = 35 is valid +lba_idx = 40 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=used *[46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +lba_idx = 31 is valid +lba_idx = 26 is valid +lba_idx = 27 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used *[117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=used +lba_idx = 28 is valid +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=stale +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=free [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used *[128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=used +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=used +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used *[36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +lba_idx = 23 is valid +lba_idx = 34 is valid +lba_idx = 35 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used *[39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used *[46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +lba_idx = 38 is valid +lba_idx = 26 is valid +lba_idx = 27 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=used *[38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=stale +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used *[116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=used +lba_idx = 21 is valid +lba_idx = 22 is valid +lba_idx = 40 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=free +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=free +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=free +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=free +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=free +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=free +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=free +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used * +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=free +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=free [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=free [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=used +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=stale +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used *[128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=stale +lba_idx = 35 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used *[48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +lba_idx = 30 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=stale +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=free [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=free [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used *[128]=stale +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=stale +lba_idx = 31 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=free +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=free +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=free +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=free +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=free +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=free +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=free +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=free +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used * +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=free +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=free +lba_idx = 26 is valid +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used * +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used * +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=used *[39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +free_page_count =10 +min_valid_count =0 +free_page_count =9 +min_valid_count =0 +free_page_count =8 +min_valid_count =0 +free_page_count =7 +min_valid_count =0 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used *[117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=stale +lba_idx = 38 is valid +lba_idx = 30 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=stale +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=free [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used *[128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=stale +lba_idx = 31 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=free +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=free +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=free +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=free +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=free +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=free +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=free +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used * +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=free +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=free +lba_idx = 32 is valid +lba_idx = 33 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =4 +free_page_count =6 +min_valid_count =4 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used *[46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +lba_idx = 24 is valid +lba_idx = 38 is valid +lba_idx = 39 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=free [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=stale +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used *[127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=stale +lba_idx = 28 is valid +lba_idx = 34 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used *[129]=stale +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used *[118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=stale +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=stale +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=stale +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used *[37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=stale +lba_idx = 21 is valid +lba_idx = 33 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=stale +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used *[48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=stale +lba_idx = 26 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=free +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=free +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=free +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=free +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=free +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=free +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=free +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=free +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=free +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used * +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=free +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=free +lba_idx = 35 is valid +lba_idx = 34 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used * +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=free [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=free [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=free [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=free [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=used +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=used * +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used *[126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=free [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=stale +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=stale +lba_idx = 37 is valid +lba_idx = 38 is valid +lba_idx = 33 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used *[38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +lba_idx = 27 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used *[39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used *[46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +lba_idx = 39 is valid +lba_idx = 40 is valid +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=stale +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used *[118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=stale +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=free +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=free +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=free +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=free +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=free +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=free +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=free +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=free +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used * +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=free +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=free +lba_idx = 31 is valid +lba_idx = 32 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used * +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used * +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used *[37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +lba_idx = 25 is valid +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used *[48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +lba_idx = 37 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=free [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=free [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=free [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=stale +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=free +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=free +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=free +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=free +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=free +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=free +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=free +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=free +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=free +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used * +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=free +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=free +lba_idx = 27 is valid +lba_idx = 31 is valid +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used * +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used *[36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used [129]=used +lba_idx = 21 is valid +lba_idx = 22 is valid +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=used +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =4 +free_page_count =6 +min_valid_count =4 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used *[116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +lba_idx = 23 is valid +lba_idx = 28 is valid +lba_idx = 29 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used *[46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +lba_idx = 21 is valid +lba_idx = 22 is valid +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used *[37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 34 is valid +lba_idx = 23 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used *[118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +lba_idx = 40 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=free [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=free [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=free [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=free [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=free +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=free +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=free +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=free +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=free +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=free +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=free +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used * +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=free +lba_idx = 32 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=used *[48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 30 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used *[117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +lba_idx = 31 is valid +lba_idx = 29 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used *[37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 34 is valid +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used *[48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=free [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=free [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =0 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=free +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=free +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=free +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=free +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=free +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=free +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=free +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=free +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=used * +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used *[117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +lba_idx = 23 is valid +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=used *[39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =4 +free_page_count =6 +min_valid_count =4 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used *[46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 39 is valid +lba_idx = 40 is valid +lba_idx = 23 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used *[116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +lba_idx = 20 is valid +lba_idx = 21 is valid +lba_idx = 22 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=free [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=free [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =0 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=free +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=free +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=free +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=free +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=free +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=free +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=free +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used * +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=free +lba_idx = 25 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=used *[38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +lba_idx = 31 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=used +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=stale +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used *[118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=stale +lba_idx = 24 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=free +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=free +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=free +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=free +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=free +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=free +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=free +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=free +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=free +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=free +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used * +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=free +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=free +lba_idx = 33 is valid +lba_idx = 34 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used * +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used * +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used *[46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 35 is valid +lba_idx = 36 is valid +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=free [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=free [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=free [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=used +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=used +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used *[128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=used +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used *[38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +lba_idx = 27 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=free +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=free +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=free +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=free +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=free +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=free +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=free +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=free +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used * +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=free +lba_idx = 23 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =0 +free_page_count =7 +min_valid_count =0 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used *[118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=stale +lba_idx = 35 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=stale +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used *[38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=used *[48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +lba_idx = 28 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=stale +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=free [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=free [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used *[128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=stale +lba_idx = 33 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=free +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=free +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=free +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=free +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=free +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=free +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=free +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used * +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=free +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=free +lba_idx = 41 is valid +lba_idx = 24 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used *[37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 21 is valid +lba_idx = 22 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=free [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=used +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used *[127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=used +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=stale +lba_idx = 27 is valid +lba_idx = 28 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used *[48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=free +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=free +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=free +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=free +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=free +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=free +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=free +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=free +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used * +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=free +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=free +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=free +lba_idx = 39 is valid +lba_idx = 40 is valid +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used * +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=used +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used * +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used *[118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +lba_idx = 21 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used *[38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +lba_idx = 33 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=used +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used *[127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=used +lba_idx = 27 is valid +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=used +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used *[48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=free +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=free +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=free +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=free +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=free +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=free +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=free +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=free +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=free +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used * +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=free +lba_idx = 21 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used * +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used * +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used *[118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=used +lba_idx = 29 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=used +[7]=used [17]=used [27]=free [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=stale +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=used +free_page_count =10 +min_valid_count =0 +free_page_count =9 +min_valid_count =0 +free_page_count =8 +min_valid_count =0 +free_page_count =7 +min_valid_count =0 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=stale +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =0 +free_page_count =7 +min_valid_count =0 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=free +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=free +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=free +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=free +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=free +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=free +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=free +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=used +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=used *[38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=free [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=free [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=used +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used *[128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=stale +lba_idx = 25 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used *[129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used *[117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=stale +lba_idx = 24 is valid +lba_idx = 40 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=stale +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=stale +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used *[46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +lba_idx = 23 is valid +lba_idx = 38 is valid +lba_idx = 39 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =4 +free_page_count =6 +min_valid_count =4 +free_page_count =5 +min_valid_count =4 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used *[35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +lba_idx = 29 is valid +lba_idx = 35 is valid +lba_idx = 36 is valid +lba_idx = 23 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +free_page_count =10 +min_valid_count =4 +free_page_count =9 +min_valid_count =4 +free_page_count =8 +min_valid_count =4 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used *[47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +lba_idx = 34 is valid +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=free [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=free [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=stale +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used *[127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=stale +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=stale +lba_idx = 37 is valid +lba_idx = 29 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used *[37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +lba_idx = 41 is valid +lba_idx = 31 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=free +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=free +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=free +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=free +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=free +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=free +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=free +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=free +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=free +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=free [121]=used +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=free [124]=used +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=free [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=free [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=used * +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =0 +free_page_count =7 +min_valid_count =0 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=used [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=used [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used *[129]=used +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =0 +free_page_count =7 +min_valid_count =0 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=used +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used *[48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +lba_idx = 36 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=stale +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used *[37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +lba_idx = 27 is valid +lba_idx = 34 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=stale +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=stale +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used *[117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=stale [129]=stale +lba_idx = 41 is valid +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=free +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=free +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=free +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=free +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=free +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=free +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=free +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=free +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=stale [129]=free +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used * +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=free +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=free +lba_idx = 21 is valid +lba_idx = 22 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used * +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=free [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=free [125]=used +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=free [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=free [128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=used * +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used *[128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=free [129]=stale +lba_idx = 33 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=stale +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=stale [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=used +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=used *[129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used *[48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=stale +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=used +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=used +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=stale +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=stale +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =0 +free_page_count =7 +min_valid_count =0 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=free +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=free +[2]=used [12]=used [22]=stale [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=free +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=free +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=free +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=free +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=free +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=free +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=used +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=used +[2]=used [12]=used [22]=free [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=free [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=used +[4]=used [14]=used [24]=free [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=used +[5]=used [15]=used [25]=free [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=free [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used [119]=stale [129]=used * +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=used *[38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 26 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=stale [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=used +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=free [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=free [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=free [126]=used +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=free [127]=used +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=used +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 10 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used *[127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=used +lba_idx = 39 is valid +lba_idx = 40 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=used +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=used [124]=stale +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used *[129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used *[118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=used +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=used +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=used *[47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 30 is valid +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=free [31]=used [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=used +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used *[37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 34 is valid +lba_idx = 35 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=free [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=used +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =3 +free_page_count =6 +min_valid_count =3 +free_page_count =5 +min_valid_count =3 +free_page_count =4 +min_valid_count =3 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used *[126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=used +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=used +lba_idx = 38 is valid +lba_idx = 33 is valid +lba_idx = 20 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=used +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=stale [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=stale +[4]=used [14]=used [24]=stale [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=stale +[5]=used [15]=used [25]=stale [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=used [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=used +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=used [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=free [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=free [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=free [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=free [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=free [115]=used [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=free [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=free [117]=used [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=free [118]=used [128]=used +[9]=used [19]=used [29]=used [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 12 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used *[118]=stale [128]=used +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=free [119]=used [129]=stale +lba_idx = 36 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=stale +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=stale +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=stale +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=free +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=free +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=used [122]=free +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=free +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=free +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=free +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=free +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=free +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=used [118]=stale [128]=free +[9]=used [19]=used [29]=used [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=used *[119]=used [129]=free +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =3 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used * +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=free +lba_idx = 26 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=used +[3]=used [13]=used [23]=stale [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=used +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used * +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =3 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =2 +free_page_count =3 +min_valid_count =2 +=======GC======= +target_nand = 2 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used *[47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used +lba_idx = 40 is valid +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=stale [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=stale [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=stale [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=stale [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=stale [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=stale [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=stale [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used +find nand_2 is empty block +[print_pca] +[0]=used [10]=used [20]=free [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=free [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=free [32]=used [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=used [112]=stale [122]=stale +[3]=used [13]=used [23]=free [33]=used [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=used +[4]=used [14]=used [24]=free [34]=used [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=used +[5]=used [15]=used [25]=free [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=free [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=free [37]=used [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=used +[8]=used [18]=used [28]=free [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=used *[49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used [129]=used +free_page_count =10 +min_valid_count =2 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =1 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 11 +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=used [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used *[38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=free [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +lba_idx = 32 is valid +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=stale [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=stale [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=stale [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=stale [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=stale [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=stale [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=stale [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=stale [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=stale [128]=stale +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used +find nand_11 is empty block +[print_pca] +[0]=used [10]=used [20]=used [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=free [120]=stale +[1]=used [11]=used [21]=used [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=used [111]=free [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=free [122]=stale +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=free [123]=stale +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=free [124]=stale +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=used [115]=free [125]=stale +[6]=used [16]=used [26]=used [36]=used [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=used [116]=free [126]=stale +[7]=used [17]=used [27]=used [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=used [117]=free [127]=stale +[8]=used [18]=used [28]=used [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=free [128]=stale +[9]=used [19]=used [29]=used *[39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=free [129]=used +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =1 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_12 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=free +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=free +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=free +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=used [113]=used [123]=free +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=used [114]=used [124]=free +[5]=used [15]=used [25]=used [35]=used [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=free +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=used [126]=free +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=free +[8]=used [18]=used [28]=stale [38]=used [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=free +[9]=used [19]=used [29]=used [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=used *[129]=free +free_page_count =10 +min_valid_count =3 +free_page_count =9 +min_valid_count =2 +free_page_count =8 +min_valid_count =2 +free_page_count =7 +min_valid_count =2 +free_page_count =6 +min_valid_count =2 +free_page_count =5 +min_valid_count =2 +free_page_count =4 +min_valid_count =1 +free_page_count =3 +min_valid_count =1 +free_page_count =2 +min_valid_count =1 +=======GC======= +target_nand = 3 +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used * +[9]=used [19]=used [29]=stale [39]=used [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=free +lba_idx = 41 is valid +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=stale [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=stale [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=stale [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=stale [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=stale [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=stale [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=stale [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=stale [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=stale [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used * +find nand_3 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=free [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=used [110]=used [120]=stale +[1]=used [11]=used [21]=stale [31]=free [41]=stale [51]=used [61]=used [71]=used [81]=used [91]=used [101]=stale [111]=used [121]=stale +[2]=used [12]=used [22]=used [32]=free [42]=used [52]=used [62]=used [72]=used [82]=used [92]=used [102]=stale [112]=used [122]=used +[3]=used [13]=used [23]=used [33]=free [43]=used [53]=used [63]=used [73]=used [83]=used [93]=used [103]=stale [113]=used [123]=used +[4]=used [14]=used [24]=used [34]=free [44]=used [54]=used [64]=used [74]=used [84]=used [94]=used [104]=stale [114]=used [124]=used +[5]=used [15]=used [25]=used [35]=free [45]=used [55]=used [65]=used [75]=used [85]=used [95]=used [105]=stale [115]=used [125]=used +[6]=used [16]=used [26]=used [36]=free [46]=used [56]=used [66]=used [76]=used [86]=used [96]=used [106]=stale [116]=stale [126]=used +[7]=used [17]=used [27]=stale [37]=free [47]=used [57]=used [67]=used [77]=used [87]=used [97]=used [107]=stale [117]=used [127]=used +[8]=used [18]=used [28]=stale [38]=free [48]=used [58]=used [68]=used [78]=used [88]=used [98]=used [108]=stale [118]=used [128]=used +[9]=used [19]=used [29]=stale [39]=free [49]=used [59]=used [69]=used [79]=used [89]=used [99]=used [109]=stale [119]=stale [129]=used * +free_page_count =10 +min_valid_count =1 +free_page_count =9 +min_valid_count =1 +free_page_count =8 +min_valid_count =1 +free_page_count =7 +min_valid_count =1 +free_page_count =6 +min_valid_count =0 +free_page_count =5 +min_valid_count =0 +free_page_count =4 +min_valid_count =0 +free_page_count =3 +min_valid_count =0 +free_page_count =2 +min_valid_count =0 +free_page_count =1 +min_valid_count =0 +=======GC======= +find nand_10 is empty block +[print_pca] +[0]=used [10]=used [20]=stale [30]=stale [40]=stale [50]=used [60]=used [70]=used [80]=used [90]=used [100]=free [110]=used [ \ No newline at end of file diff --git a/Final/make_ioctl b/Final/make_ioctl new file mode 100644 index 000000000..210920a96 --- /dev/null +++ b/Final/make_ioctl @@ -0,0 +1,2 @@ +gcc -Wall ssd_fuse.c `pkg-config fuse3 --cflags --libs` -D_FILE_OFFSET_BITS=64 -o ssd_fuse + diff --git a/Final/make_ssd b/Final/make_ssd new file mode 100755 index 000000000..3659945ad --- /dev/null +++ b/Final/make_ssd @@ -0,0 +1,6 @@ +gcc -Wall ssd_fuse.c `pkg-config fuse3 --cflags --libs` -D_FILE_OFFSET_BITS=64 -o ssd_fuse +gcc -Wall ssd_fuse_dut.c -o ssd_fuse_dut +fusermount -zu /tmp/ssd +rm -rf /tmp/ssd +mkdir /tmp/ssd +make run diff --git a/Final/makefile b/Final/makefile new file mode 100644 index 000000000..2812f9871 --- /dev/null +++ b/Final/makefile @@ -0,0 +1,12 @@ +all: + gcc -Wall ssd_fuse.c `pkg-config fuse3 --cflags --libs` -D_FILE_OFFSET_BITS=64 -o ssd_fuse + gcc -Wall ssd_fuse_dut.c -o ssd_fuse_dut + +clean: + fusermount -zu /tmp/ssd + rm -rf /tmp/ssd + mkdir /tmp/ssd + +run: + ./ssd_fuse -d /tmp/ssd + diff --git a/Final/ssd_fuse.c b/Final/ssd_fuse.c new file mode 100644 index 000000000..308fd1a28 --- /dev/null +++ b/Final/ssd_fuse.c @@ -0,0 +1,586 @@ +/* + FUSE ssd: FUSE ioctl example + Copyright (C) 2008 SUSE Linux Products GmbH + Copyright (C) 2008 Tejun Heo + This program can be distributed under the terms of the GNU GPLv2. + See the file COPYING. +*/ +#define FUSE_USE_VERSION 35 +#include +#include +#include +#include +#include +#include +#include +#include +#include "ssd_fuse_header.h" +#define SSD_NAME "ssd_file" +enum +{ + SSD_NONE, + SSD_ROOT, + SSD_FILE, +}; + +FILE * debug; +static size_t physic_size; +static size_t logic_size; +static size_t host_write_size; +static size_t nand_write_size; + +typedef union pca_rule PCA_RULE; +union pca_rule +{ + unsigned int pca; + struct + { + unsigned int lba : 16; // page + unsigned int nand: 16; // block + } fields; +}; + +PCA_RULE curr_pca; +static unsigned int get_next_pca(); + +unsigned int* L2P,* P2L,* valid_count, free_block_number; + +static int ssd_resize(size_t new_size) +{ + //set logic size to new_size + if (new_size > NAND_SIZE_KB * 1024) + { + return -ENOMEM; + } + else + { + logic_size = new_size; + return 0; + } + +} + +static int ssd_expand(size_t new_size) +{ + //logic must less logic limit + + if (new_size > logic_size) + { + return ssd_resize(new_size); + } + + return 0; +} + +static int nand_read(char* buf, int pca) +{ + char nand_name[100]; + FILE* fptr; + + PCA_RULE my_pca; + my_pca.pca = pca; + snprintf(nand_name, 100, "%s/nand_%d", NAND_LOCATION, my_pca.fields.nand); + //read + if ( (fptr = fopen(nand_name, "r") )) + { + fseek( fptr, my_pca.fields.lba * 512, SEEK_SET ); + fread(buf, 1, 512, fptr); + fclose(fptr); + } + else + { + printf("open file fail at nand read pca = %d\n", pca); + return -EINVAL; + } + return 512; +} +static int nand_write(const char* buf, int pca) +{ + char nand_name[100]; + FILE* fptr; + + PCA_RULE my_pca; + my_pca.pca = pca; + snprintf(nand_name, 100, "%s/nand_%d", NAND_LOCATION, my_pca.fields.nand); // parse block + + //write + if ( (fptr = fopen(nand_name, "r+"))) + { + fseek( fptr, my_pca.fields.lba * 512, SEEK_SET ); // parse page + fwrite(buf, 1, 512, fptr); + fclose(fptr); + physic_size ++; + valid_count[my_pca.fields.nand]++; + } + else + { + printf("open file fail at nand (%s) write pca = %d, return %d\n", nand_name, pca, -EINVAL); + return -EINVAL; + } + + nand_write_size += 512; + return 512; +} + +static int nand_erase(int block_index) +{ + char nand_name[100]; + FILE* fptr; + snprintf(nand_name, 100, "%s/nand_%d", NAND_LOCATION, block_index); + fptr = fopen(nand_name, "w"); + if (fptr == NULL) + { + printf("erase nand_%d fail", block_index); + return 0; + } + fclose(fptr); + valid_count[block_index] = FREE_BLOCK; + free_block_number++; + return 1; +} + + +void print_pca() +{ + fprintf(debug,"[print_pca]\n"); + for(int lba = 0 ; lba < PAGE_PER_BLOCK ; lba ++){ + for(int nand = 0; nand < PHYSICAL_NAND_NUM ; nand++){ + + if(P2L[nand*10+lba] == STALE_PCA) + fprintf(debug,"[%d]=stale\t",nand * 10 + lba); + else if(P2L[nand*10+lba] == INVALID_PCA) + fprintf(debug,"[%d]=free\t",nand * 10 + lba); + else + fprintf(debug,"[%d]=used\t",nand * 10 + lba); + + if(nand*10+lba == curr_pca.fields.nand * 10 + curr_pca.fields.lba) + fprintf(debug, "*"); + } + fprintf(debug,"\n"); + } + //fflush(debug); +} + +int find_empty_block() +{ + int empty_page_count = 0; + + for(int nand = 0 ; nand < PHYSICAL_NAND_NUM; nand ++){ + empty_page_count = 0; + for(int lba = 0; lba < PAGE_PER_BLOCK; lba++){ + if(P2L[nand*10+lba] == STALE_PCA) + empty_page_count++; + } + if(empty_page_count==10){ + fprintf(debug,"find nand_%d is empty block\n",nand); + //fflush(debug); + return nand; + } + } + return -1; +} + +int try_free_a_block() +{ + int free_block_nand = find_empty_block(); + if(free_block_nand != -1){ + for(int lba = 0; lba < PAGE_PER_BLOCK; lba++) + P2L[free_block_nand*10 + lba] = INVALID_PCA; + nand_erase(free_block_nand); + print_pca(); + return 1; + } + return 0; +} + +static unsigned int get_next_block() +{ + // printf("[get_next_block]\n"); + for (int i = 0; i < PHYSICAL_NAND_NUM; i++) + { + if (valid_count[(curr_pca.fields.nand + i) % PHYSICAL_NAND_NUM] == FREE_BLOCK) + { + curr_pca.fields.nand = (curr_pca.fields.nand + i) % PHYSICAL_NAND_NUM; + curr_pca.fields.lba = 0; + free_block_number--; + valid_count[curr_pca.fields.nand] = 0; + return curr_pca.pca; + } + } + return OUT_OF_BLOCK; +} + +static unsigned int get_next_pca() +{ + // printf("[get_next_pca]\n"); + if (curr_pca.pca == INVALID_PCA) + { + //init + curr_pca.pca = 0; + valid_count[0] = 0; + free_block_number--; + return curr_pca.pca; + } + + if(curr_pca.fields.lba == 9) + { + int temp = get_next_block(); + if (temp == OUT_OF_BLOCK) + { + fprintf(debug, "=======OUT_OF_BLOCK=======\n"); + //fflush(debug); + return OUT_OF_BLOCK; + } + else if(temp == -EINVAL) + { + return -EINVAL; + } + else + { + return temp; + } + } + else + { + curr_pca.fields.lba += 1; + } + return curr_pca.pca; + +} + + +static int ftl_read( char* buf, size_t lba) +{ + // TODO + unsigned int pca = L2P[lba]; + if(pca != INVALID_PCA) + nand_read(buf,pca); + + return 0; +} + +void do_GC() +{ + fprintf(debug, "=======GC=======\n"); + char * mov_buf = calloc(512, sizeof(char)); + if(!try_free_a_block()){ // can't direct release a block, move vaild to new pca until free a block + + // find block that have least valid + int min_valid_count = 100, target_nand = -1; + for(int nand = 0 ; nand < PHYSICAL_NAND_NUM ; nand ++){ + int valid_count = 0; + for(int lba = 0; lba < PAGE_PER_BLOCK ; lba++){ + if(P2L[nand*10+lba] != STALE_PCA && P2L[nand*10+lba] != INVALID_PCA) + valid_count ++; + } + if(min_valid_count > valid_count && valid_count > 0 && nand != curr_pca.fields.nand) { + min_valid_count = valid_count; + target_nand = nand; + } + } + fprintf(debug, "target_nand = %d\n",target_nand); + print_pca(); + for(int lba = 0; lba < PAGE_PER_BLOCK ; lba++){ + if(P2L[target_nand*10+lba] != STALE_PCA && P2L[target_nand*10+lba] != INVALID_PCA ){ // vaild + PCA_RULE mov_pca, valid_pca; + // get valid_pca + int lba_idx = P2L[target_nand*10+lba]; + valid_pca.pca = L2P[lba_idx]; + fprintf(debug, "lba_idx = %d is valid\n",lba_idx); + // move to new pca + mov_pca.pca = get_next_pca(); + nand_read(mov_buf,valid_pca.pca); + nand_write(mov_buf,mov_pca.pca); + L2P[lba_idx] = mov_pca.pca; // update L2P + P2L[mov_pca.fields.nand * 10 + mov_pca.fields.lba] = lba_idx; // update P2L + + P2L[target_nand*10+lba] = STALE_PCA; // make stale + } + } + print_pca(); + try_free_a_block(); + } +} + +static int ftl_write(const char* buf,size_t lba_range, size_t lba) +{ + //TODO + int idx,pca_idx; + + for(idx = 0 ; idx valid_count && nand != curr_pca.fields.nand) { + min_valid_count = valid_count; + } + } + // print_pca(); + int free_page_count = PAGE_PER_BLOCK - curr_pca.fields.lba; + + fprintf(debug, "free_page_count =%d\n",free_page_count); + fprintf(debug, "min_valid_count =%d\n",min_valid_count); + if(free_page_count == min_valid_count + 1) + do_GC(); + } + + if(L2P[lba+idx] != INVALID_PCA){// Find stale page + PCA_RULE stale_pca; + // fprintf(debug, "[stale]lba_idx = %ld\n",lba+idx); + // fflush(debug); + stale_pca.pca = L2P[lba+idx]; + P2L[stale_pca.fields.nand * 10 + stale_pca.fields.lba] = STALE_PCA; + } + + PCA_RULE cur_pca; + cur_pca.pca = get_next_pca();// allocate new pca + pca_idx = cur_pca.fields.nand * 10 + cur_pca.fields.lba; + // fprintf(debug,"pca_idx = %d\n",pca_idx); + // fflush(debug); + L2P[lba+idx] = cur_pca.pca; // update L2P + P2L[pca_idx] = lba+idx; // update P2L + nand_write(buf+idx*512,cur_pca.pca); // call nand_write + } + return 0; +} + + + +static int ssd_file_type(const char* path) +{ + if (strcmp(path, "/") == 0) + { + return SSD_ROOT; + } + if (strcmp(path, "/" SSD_NAME) == 0) + { + return SSD_FILE; + } + return SSD_NONE; +} +static int ssd_getattr(const char* path, struct stat* stbuf, + struct fuse_file_info* fi) +{ + // printf("[ssd_getattr]\n"); + (void) fi; + stbuf->st_uid = getuid(); + stbuf->st_gid = getgid(); + stbuf->st_atime = stbuf->st_mtime = time(NULL); + switch (ssd_file_type(path)) + { + case SSD_ROOT: + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 2; + break; + case SSD_FILE: + stbuf->st_mode = S_IFREG | 0644; + stbuf->st_nlink = 1; + stbuf->st_size = logic_size; + break; + case SSD_NONE: + return -ENOENT; + } + return 0; +} +static int ssd_open(const char* path, struct fuse_file_info* fi) +{ + // printf("[ssd_open]\n"); + (void) fi; + if (ssd_file_type(path) != SSD_NONE) + { + return 0; + } + return -ENOENT; +} + +static int ssd_do_read(char* buf, size_t size, off_t offset) +{ + int tmp_lba, tmp_lba_range; + char* tmp_buf; + //off limit + if ((offset ) >= logic_size) + { + return 0; + } + if ( size > logic_size - offset) + { + //is valid data section + size = logic_size - offset; + } + + tmp_lba = offset / 512; + tmp_lba_range = (offset + size - 1) / 512 - (tmp_lba) + 1; + tmp_buf = calloc(tmp_lba_range * 512, sizeof(char)); + + for (int i = 0; i < tmp_lba_range; i++) { + // TODO + ftl_read(tmp_buf+i*512,tmp_lba+i); + } + + memcpy(buf, tmp_buf + offset % 512, size); + + + free(tmp_buf); + return size; +} +static int ssd_read(const char* path, char* buf, size_t size, + off_t offset, struct fuse_file_info* fi) +{ + printf("[ssd_read]\n"); + (void) fi; + if (ssd_file_type(path) != SSD_FILE) + { + return -EINVAL; + } + return ssd_do_read(buf, size, offset); +} +static int ssd_do_write(const char* buf, size_t size, off_t offset) +{ + // fprintf(debug, "\nsize = %ld, offset = %ld, strlen(buf) = %ld\n", size, offset, strlen(buf)); + // fflush(debug); + int tmp_lba, tmp_lba_range, tmp_offset, idx; + // int process_size, curr_size, remain_size, rst; + char* tmp_buf; + + host_write_size += size; + if (ssd_expand(offset + size) != 0) + { + return -ENOMEM; + } + + tmp_lba = offset / 512; // start lba + tmp_offset = offset % 512; // current offset + tmp_lba_range = (offset + size - 1) / 512 - (tmp_lba) + 1; // will use range + tmp_buf = calloc(tmp_lba_range * 512, sizeof(char)); + + for (idx = 0; idx < tmp_lba_range; idx++) + { + ftl_read(tmp_buf+idx*512,tmp_lba+idx); + } + + memcpy(tmp_buf+tmp_offset, buf, size); + ftl_write(tmp_buf, tmp_lba_range, tmp_lba); + return size; +} +static int ssd_write(const char* path, const char* buf, size_t size, + off_t offset, struct fuse_file_info* fi) +{ + printf("[ssd_write]\n"); + (void) fi; + if (ssd_file_type(path) != SSD_FILE) + { + return -EINVAL; + } + return ssd_do_write(buf, size, offset); +} +static int ssd_truncate(const char* path, off_t size, + struct fuse_file_info* fi) +{ + printf("[ssd_truncate]\n"); + (void) fi; + memset(L2P, INVALID_PCA, sizeof(int) * LOGICAL_NAND_NUM * PAGE_PER_BLOCK); + memset(P2L, INVALID_LBA, sizeof(int) * PHYSICAL_NAND_NUM * PAGE_PER_BLOCK); + memset(valid_count, FREE_BLOCK, sizeof(int) * PHYSICAL_NAND_NUM); + curr_pca.pca = INVALID_PCA; + free_block_number = PHYSICAL_NAND_NUM; + if (ssd_file_type(path) != SSD_FILE) + { + return -EINVAL; + } + + return ssd_resize(size); +} +static int ssd_readdir(const char* path, void* buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info* fi, + enum fuse_readdir_flags flags) +{ + printf("[ssd_readdir]\n"); + (void) fi; + (void) offset; + (void) flags; + if (ssd_file_type(path) != SSD_ROOT) + { + return -ENOENT; + } + filler(buf, ".", NULL, 0, 0); + filler(buf, "..", NULL, 0, 0); + filler(buf, SSD_NAME, NULL, 0, 0); + return 0; +} +static int ssd_ioctl(const char* path, unsigned int cmd, void* arg, + struct fuse_file_info* fi, unsigned int flags, void* data) +{ + // printf("[ssd_ioctl]\n"); + if (ssd_file_type(path) != SSD_FILE) + { + return -EINVAL; + } + if (flags & FUSE_IOCTL_COMPAT) + { + return -ENOSYS; + } + switch (cmd) + { + case SSD_GET_LOGIC_SIZE: + *(size_t*)data = logic_size; + return 0; + case SSD_GET_PHYSIC_SIZE: + *(size_t*)data = physic_size; + return 0; + case SSD_GET_WA: + *(double*)data = (double)nand_write_size / (double)host_write_size; + return 0; + } + return -EINVAL; +} + +static const struct fuse_operations ssd_oper = +{ + .getattr = ssd_getattr, + .readdir = ssd_readdir, + .truncate = ssd_truncate, + .open = ssd_open, + .read = ssd_read, + .write = ssd_write, + .ioctl = ssd_ioctl, +}; + +int main(int argc, char* argv[]) +{ + int idx; + char nand_name[100]; + physic_size = 0; + logic_size = 0; + curr_pca.pca = INVALID_PCA; + free_block_number = PHYSICAL_NAND_NUM; + L2P = malloc(LOGICAL_NAND_NUM * PAGE_PER_BLOCK * sizeof(int)); + memset(L2P, INVALID_PCA, sizeof(int) * LOGICAL_NAND_NUM * PAGE_PER_BLOCK); + P2L = malloc(PHYSICAL_NAND_NUM * PAGE_PER_BLOCK * sizeof(int)); + memset(P2L, INVALID_LBA, sizeof(int) * PHYSICAL_NAND_NUM * PAGE_PER_BLOCK); + valid_count = malloc(PHYSICAL_NAND_NUM * sizeof(int)); + memset(valid_count, FREE_BLOCK, sizeof(int) * PHYSICAL_NAND_NUM); + + debug = fopen ("log.txt", "w+"); + //create nand file + for (idx = 0; idx < PHYSICAL_NAND_NUM; idx++) + { + FILE* fptr; + snprintf(nand_name, 100, "%s/nand_%d", NAND_LOCATION, idx); + fptr = fopen(nand_name, "w"); + if (fptr == NULL) + { + printf("open fail"); + } + fclose(fptr); + } + return fuse_main(argc, argv, &ssd_oper, NULL); +} diff --git a/Final/ssd_fuse_dut.c b/Final/ssd_fuse_dut.c new file mode 100644 index 000000000..441012768 --- /dev/null +++ b/Final/ssd_fuse_dut.c @@ -0,0 +1,170 @@ +/* + FUSE ssdlient: FUSE ioctl example client + Copyright (C) 2008 SUSE Linux Products GmbH + Copyright (C) 2008 Tejun Heo + This program can be distributed under the terms of the GNU GPLv2. + See the file COPYING. +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ssd_fuse_header.h" +#include +const char* usage = + "Usage: ssd_fuse SSD_FILE COMMAND\n" + "\n" + "COMMANDS\n" + " l : get logic size \n" + " p : get physical size \n" + " r SIZE [OFF] : read SIZE bytes @ OFF (dfl 0) and output to stdout\n" + " w SIZE [OFF] : write SIZE bytes @ OFF (dfl 0) from random\n" + " W : write amplification factor\n" + "\n"; +static int do_rw(FILE* fd, int is_read, size_t size, off_t offset) +{ + char* buf; + int idx; + ssize_t ret; + buf = calloc(1, size); + + if (!buf) + { + fprintf(stderr, "failed to allocated %zu bytes\n", size); + return -1; + } + if (is_read) + { + printf("dut do read size %ld, off %d\n", size, (int)offset); + fseek( fd, offset, SEEK_SET ); + ret = fread( buf, 1, size, fd); + if (ret >= 0) + { + fwrite(buf, 1, ret, stdout); + } + } + else + { + for ( idx = 0; idx < size; idx++) + { + buf[idx] = idx; + } + printf("dut do write size %ld, off %d\n", size, (int)offset); + fseek( fd, offset, SEEK_SET ); + printf("fseek \n"); + ret = fwrite(buf, 1, size, fd); + //arg.size = fread(arg.buf, 1, size, stdin); + fprintf(stderr, "Writing %zu bytes\n", size); + } + if (ret < 0) + { + perror("ioctl"); + } + + free(buf); + return ret; +} + +int main(int argc, char** argv) +{ + size_t param[2] = { }; + size_t size; + char cmd; + char* path; + FILE* fptr; + int fd, i, rc; + if (argc < 3) + { + goto usage; + } + path = argv[1]; + cmd = tolower(argv[2][0]); + cmd = argv[2][0]; + argc -= 3; + argv += 3; + for (i = 0; i < argc; i++) + { + char* endp; + param[i] = strtoul(argv[i], &endp, 0); + if (endp == argv[i] || *endp != '\0') + { + goto usage; + } + } + switch (cmd) + { + case 'l': + fd = open(path, O_RDWR); + if (fd < 0) + { + perror("open"); + return 1; + } + if (ioctl(fd, SSD_GET_LOGIC_SIZE, &size)) + { + perror("ioctl"); + goto error; + } + printf("%zu\n", size); + close(fd); + return 0; + case 'p': + fd = open(path, O_RDWR); + if (fd < 0) + { + perror("open"); + return 1; + } + if (ioctl(fd, SSD_GET_PHYSIC_SIZE, &size)) + { + perror("ioctl"); + goto error; + } + printf("%zu\n", size); + close(fd); + return 0; + case 'r': + case 'w': + if ( !(fptr = fopen(path, "r+"))) + { + perror("open"); + return 1; + } + rc = do_rw(fptr, cmd == 'r', param[0], param[1]); + if (rc < 0) + { + goto error; + } + fprintf(stderr, "transferred %d bytes \n", rc); + + fclose(fptr); + return 0; + case 'W': + fd = open(path, O_RDWR); + if (fd < 0) + { + perror("open"); + return 1; + } + double wa; + if (ioctl(fd, SSD_GET_WA, &wa)) + { + perror("ioctl"); + goto error; + } + printf("%f\n", wa); + close(fd); + return 0; + } +usage: + fprintf(stderr, "%s", usage); + return 1; +error: + + return 1; +} \ No newline at end of file diff --git a/Final/ssd_fuse_header.h b/Final/ssd_fuse_header.h new file mode 100644 index 000000000..184313841 --- /dev/null +++ b/Final/ssd_fuse_header.h @@ -0,0 +1,30 @@ +/* + FUSE-ioctl: ioctl support for FUSE + Copyright (C) 2008 SUSE Linux Products GmbH + Copyright (C) 2008 Tejun Heo + This program can be distributed under the terms of the GNU GPLv2. + See the file COPYING. +*/ +#include +#include +#include +#define PHYSICAL_NAND_NUM (13) +#define LOGICAL_NAND_NUM (10) +#define NAND_SIZE_KB (50) + +#define INVALID_PCA (0xFFFFFFFF) +#define STALE_PCA (0xFFFFFFFE) + +#define INVALID_LBA (0xFFFFFFFF) +#define FREE_BLOCK (0xFFFFFFFF) +#define OUT_OF_BLOCK (0xFFFF) +#define FULL_PCA (0xFFFFFFFE) +#define PAGE_PER_BLOCK (10) +#define NAND_LOCATION "/home/frank/Desktop/osdi/osc2022/Final/nand" + +enum +{ + SSD_GET_LOGIC_SIZE = _IOR('E', 0, size_t), + SSD_GET_PHYSIC_SIZE = _IOR('E', 1, size_t), + SSD_GET_WA = _IOR('E', 2, size_t), +}; diff --git a/Final/ssd_fuse_lab.docx b/Final/ssd_fuse_lab.docx new file mode 100644 index 000000000..852071cbf Binary files /dev/null and b/Final/ssd_fuse_lab.docx differ diff --git a/Final/test.sh b/Final/test.sh new file mode 100755 index 000000000..85fa40410 --- /dev/null +++ b/Final/test.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +SSD_FILE="/tmp/ssd/ssd_file" +GOLDEN="/tmp/ssd_file_golden" +TEMP="/tmp/temp" +touch ${GOLDEN} +truncate -s 0 ${SSD_FILE} +truncate -s 0 ${GOLDEN} + +rand(){ + min=$1 + max=$(($2-$min)) + num=$(cat /dev/urandom | head -n 10 | cksum | awk -F ' ' '{print $1}') + echo $(($num%$max)) +} + +case "$1" in + "test1") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + ;; + "test2") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 11264 > ${TEMP} + for i in $(seq 0 9) + do + dd if=${TEMP} iflag=skip_bytes skip=$(($i*1024)) of=${GOLDEN} oflag=seek_bytes seek=$(($i*5120)) bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=$(($i*1024)) of=${SSD_FILE} oflag=seek_bytes seek=$(($i*5120)) bs=1024 count=1 conv=notrunc 2> /dev/null + done + dd if=${TEMP} iflag=skip_bytes skip=10240 of=${GOLDEN} oflag=seek_bytes seek=0 bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=10240 of=${SSD_FILE} oflag=seek_bytes seek=0 bs=1024 count=1 conv=notrunc 2> /dev/null + ;; + "test3") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 11264 > ${TEMP} + for i in $(seq 0 49) + do + dd if=${TEMP} iflag=skip_bytes skip=$(($i*512)) of=${GOLDEN} oflag=seek_bytes seek=$(($i*1024)) bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=$(($i*512)) of=${SSD_FILE} oflag=seek_bytes seek=$(($i*1024)) bs=1024 count=1 conv=notrunc 2> /dev/null + done + dd if=${TEMP} iflag=skip_bytes skip=10240 of=${GOLDEN} oflag=seek_bytes seek=0 bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=10240 of=${SSD_FILE} oflag=seek_bytes seek=0 bs=1024 count=1 conv=notrunc 2> /dev/null + ;; + "test4") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 > ${TEMP} + for i in $(seq 0 400) + do + skip_b=$(shuf -i 10240-20480 -n 1) + seek_b=$(shuf -i 10240-20480 -n 1) + echo $skip_b $seek_b + dd if=${TEMP} iflag=skip_bytes skip=${skip_b} of=${GOLDEN} oflag=seek_bytes seek=${seek_b} bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=${skip_b} of=${SSD_FILE} oflag=seek_bytes seek=${seek_b} bs=1024 count=1 conv=notrunc 2> /dev/null + if [ ! -z "$(diff ${GOLDEN} ${SSD_FILE})" ]; then + echo -1 + exit 1 + fi + done + ;; + "test5") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 > ${TEMP} + skip_b=$(shuf -i 0-50176 -n 1) + seek_b=$(shuf -i 0-50176 -n 1) + for i in $(seq 0 100) + do + dd if=${TEMP} iflag=skip_bytes skip=${skip_b} of=${GOLDEN} oflag=seek_bytes seek=${seek_b} bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=${skip_b} of=${SSD_FILE} oflag=seek_bytes seek=${seek_b} bs=1024 count=1 conv=notrunc 2> /dev/null + done + ;; + "test6") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 11264 > ${TEMP} + for i in $(seq 0 9) + do + dd if=${TEMP} skip=$(($i1024)) of=${GOLDEN} iflag=skip_bytes oflag=seek_bytes seek=$(($i5120)) bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} skip=$(($i1024)) of=${SSD_FILE} iflag=skip_bytes oflag=seek_bytes seek=$(($i5120)) bs=1024 count=1 conv=notrunc 2> /dev/null + done + dd if=${TEMP} skip=3000 of=${GOLDEN} iflag=skip_bytes oflag=seek_bytes seek=0 bs=2048 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} skip=3000 of=${SSD_FILE} iflag=skip_bytes oflag=seek_bytes seek=0 bs=2048 count=1 conv=notrunc 2> /dev/null + ;; + "test7") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 11264 > ${TEMP} + for i in $(seq 0 1000) + do + dd if=${TEMP} skip=1024 of=${GOLDEN} iflag=skip_bytes oflag=seek_bytes seek=6789 bs=5000 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} skip=1024 of=${SSD_FILE} iflag=skip_bytes oflag=seek_bytes seek=6789 bs=5000 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} skip=2024 of=${GOLDEN} iflag=skip_bytes oflag=seek_bytes seek=123 bs=777 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} skip=2024 of=${SSD_FILE} iflag=skip_bytes oflag=seek_bytes seek=123 bs=777 count=1 conv=notrunc 2> /dev/null + done + ;; + *) + printf "Usage: sh test.sh test_pattern\n" + printf "\n" + printf "test_pattern\n" + printf "test1: Sequential write whole SSD size(51200bytes)\n" + printf " test basic SSD read & write\n" + printf "test2:\n" + printf " 1: Sequential write whole SSD size(51200bytes)\n" + printf " 2: Override 0, 1, 10, 11, 20, 21, 30, 31, 40, 41, 50, 51, 60, 61, 70, 71, 80, 81, 90, 91 page \n" + printf " 2: Override 0, 1 page \n" + printf " test GC's result\n" + return + ;; +esac + +# check +diff ${GOLDEN} ${SSD_FILE} +if [ $? -eq 0 ] +then + echo "success!" +else + echo "fail!" +fi + +echo "WA:" +./ssd_fuse_dut /tmp/ssd/ssd_file W +rm -rf ${TEMP} ${GOLDEN} \ No newline at end of file diff --git a/Final/test1.sh b/Final/test1.sh new file mode 100755 index 000000000..85fa40410 --- /dev/null +++ b/Final/test1.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +SSD_FILE="/tmp/ssd/ssd_file" +GOLDEN="/tmp/ssd_file_golden" +TEMP="/tmp/temp" +touch ${GOLDEN} +truncate -s 0 ${SSD_FILE} +truncate -s 0 ${GOLDEN} + +rand(){ + min=$1 + max=$(($2-$min)) + num=$(cat /dev/urandom | head -n 10 | cksum | awk -F ' ' '{print $1}') + echo $(($num%$max)) +} + +case "$1" in + "test1") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + ;; + "test2") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 11264 > ${TEMP} + for i in $(seq 0 9) + do + dd if=${TEMP} iflag=skip_bytes skip=$(($i*1024)) of=${GOLDEN} oflag=seek_bytes seek=$(($i*5120)) bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=$(($i*1024)) of=${SSD_FILE} oflag=seek_bytes seek=$(($i*5120)) bs=1024 count=1 conv=notrunc 2> /dev/null + done + dd if=${TEMP} iflag=skip_bytes skip=10240 of=${GOLDEN} oflag=seek_bytes seek=0 bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=10240 of=${SSD_FILE} oflag=seek_bytes seek=0 bs=1024 count=1 conv=notrunc 2> /dev/null + ;; + "test3") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 11264 > ${TEMP} + for i in $(seq 0 49) + do + dd if=${TEMP} iflag=skip_bytes skip=$(($i*512)) of=${GOLDEN} oflag=seek_bytes seek=$(($i*1024)) bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=$(($i*512)) of=${SSD_FILE} oflag=seek_bytes seek=$(($i*1024)) bs=1024 count=1 conv=notrunc 2> /dev/null + done + dd if=${TEMP} iflag=skip_bytes skip=10240 of=${GOLDEN} oflag=seek_bytes seek=0 bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=10240 of=${SSD_FILE} oflag=seek_bytes seek=0 bs=1024 count=1 conv=notrunc 2> /dev/null + ;; + "test4") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 > ${TEMP} + for i in $(seq 0 400) + do + skip_b=$(shuf -i 10240-20480 -n 1) + seek_b=$(shuf -i 10240-20480 -n 1) + echo $skip_b $seek_b + dd if=${TEMP} iflag=skip_bytes skip=${skip_b} of=${GOLDEN} oflag=seek_bytes seek=${seek_b} bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=${skip_b} of=${SSD_FILE} oflag=seek_bytes seek=${seek_b} bs=1024 count=1 conv=notrunc 2> /dev/null + if [ ! -z "$(diff ${GOLDEN} ${SSD_FILE})" ]; then + echo -1 + exit 1 + fi + done + ;; + "test5") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 > ${TEMP} + skip_b=$(shuf -i 0-50176 -n 1) + seek_b=$(shuf -i 0-50176 -n 1) + for i in $(seq 0 100) + do + dd if=${TEMP} iflag=skip_bytes skip=${skip_b} of=${GOLDEN} oflag=seek_bytes seek=${seek_b} bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} iflag=skip_bytes skip=${skip_b} of=${SSD_FILE} oflag=seek_bytes seek=${seek_b} bs=1024 count=1 conv=notrunc 2> /dev/null + done + ;; + "test6") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 11264 > ${TEMP} + for i in $(seq 0 9) + do + dd if=${TEMP} skip=$(($i1024)) of=${GOLDEN} iflag=skip_bytes oflag=seek_bytes seek=$(($i5120)) bs=1024 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} skip=$(($i1024)) of=${SSD_FILE} iflag=skip_bytes oflag=seek_bytes seek=$(($i5120)) bs=1024 count=1 conv=notrunc 2> /dev/null + done + dd if=${TEMP} skip=3000 of=${GOLDEN} iflag=skip_bytes oflag=seek_bytes seek=0 bs=2048 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} skip=3000 of=${SSD_FILE} iflag=skip_bytes oflag=seek_bytes seek=0 bs=2048 count=1 conv=notrunc 2> /dev/null + ;; + "test7") + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 51200 | tee ${SSD_FILE} > ${GOLDEN} 2> /dev/null + cat /dev/urandom | tr -dc '[:alpha:][:digit:]' | head -c 11264 > ${TEMP} + for i in $(seq 0 1000) + do + dd if=${TEMP} skip=1024 of=${GOLDEN} iflag=skip_bytes oflag=seek_bytes seek=6789 bs=5000 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} skip=1024 of=${SSD_FILE} iflag=skip_bytes oflag=seek_bytes seek=6789 bs=5000 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} skip=2024 of=${GOLDEN} iflag=skip_bytes oflag=seek_bytes seek=123 bs=777 count=1 conv=notrunc 2> /dev/null + dd if=${TEMP} skip=2024 of=${SSD_FILE} iflag=skip_bytes oflag=seek_bytes seek=123 bs=777 count=1 conv=notrunc 2> /dev/null + done + ;; + *) + printf "Usage: sh test.sh test_pattern\n" + printf "\n" + printf "test_pattern\n" + printf "test1: Sequential write whole SSD size(51200bytes)\n" + printf " test basic SSD read & write\n" + printf "test2:\n" + printf " 1: Sequential write whole SSD size(51200bytes)\n" + printf " 2: Override 0, 1, 10, 11, 20, 21, 30, 31, 40, 41, 50, 51, 60, 61, 70, 71, 80, 81, 90, 91 page \n" + printf " 2: Override 0, 1 page \n" + printf " test GC's result\n" + return + ;; +esac + +# check +diff ${GOLDEN} ${SSD_FILE} +if [ $? -eq 0 ] +then + echo "success!" +else + echo "fail!" +fi + +echo "WA:" +./ssd_fuse_dut /tmp/ssd/ssd_file W +rm -rf ${TEMP} ${GOLDEN} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 000000000..6b49502c8 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# osc2022 +## Author + +| 學號 | GitHub 帳號 | 姓名 | Email | +| --- | ----------- | --- | --- | +|`309554042`| `JusticeLeee` | `李政毅` | franklp97531@gmail.com | + +## Lab 1: Hello World +- [x] `basic 1` +- [x] `basic 2` +- [x] `basic 3` +- [x] `advanced 1` + +## Lab 2: Booting +- [x] `basic 1` +- [x] `basic 2` +- [x] `basic 3` +- [x] `advanced 1` +- [ ] `advanced 2` + +## Lab 3: Exception and Interrupt +- [x] `basic 1` +- [x] `basic 2` +- [x] `basic 3` +- [ ] `advanced 1` +- [ ] `advanced 2` + +## Lab 4: Allocator +- [x] `basic 1` +- [x] `basic 2` +- [ ] `advanced 1` +- [ ] `advanced 2` +- [ ] `advanced 3` + +## Lab 5: Thread and User Process +- [x] `basic 1` +- [x] `basic 2` +- [x] `basic 3` +- [ ] `advanced 1` + +## Lab 6 : Virtual Memory +- [x] `basic 1` +- [x] `basic 2` +- [x] `basic 3` +- [ ] `advanced 1` +- [ ] `advanced 2` +- [ ] `advanced 3` + +## Lab 7 : Virtual File System +- [x] `basic 1` +- [x] `basic 2` +- [x] `basic 3` +- [x] `basic 4` +- [x] `advanced 1` +- [x] `advanced 2` + +## Lab 8 : Non-volatile Storage +- [x] `basic 1` +- [x] `basic 2` +- [ ] `advanced 1` diff --git a/lab1/README.md b/lab1/README.md deleted file mode 100644 index c3f1e8de5..000000000 --- a/lab1/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# osc2022 -## Author - -| 學號 | GitHub 帳號 | 姓名 | Email | -| --- | ----------- | --- | --- | -|`309554042`| `JusticeLeee` | `李政毅` | franklp97531@gmail.com | - -## How to build - -```bash -make -``` -## How to run - -```bash -make run -``` -## How to burn it into pi3 -```bash -sudo screen /dev/ttyUSB0 115200 -``` -## Note - -copy some string.h source for use strcmp \ No newline at end of file diff --git a/lab2/README.md b/lab2/README.md deleted file mode 100644 index 78ddcba99..000000000 --- a/lab2/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# osc2022 -## Author - -| 學號 | GitHub 帳號 | 姓名 | Email | -| --- | ----------- | --- | --- | -|`309554042`| `JusticeLeee` | `李政毅` | franklp97531@gmail.com | - -## How to build - -```bash -./make.sh -``` -## How to run - -```bash -make run -``` -## How to burn it into pi3 -```bash -./rus.sh # write kernel to rpi3 through uart -sudo screen /dev/ttyUSB0 115200 -``` -## Note - -copy some string.h source for use strcmp \ No newline at end of file diff --git a/lab3/README.md b/lab3/README.md deleted file mode 100644 index 78ddcba99..000000000 --- a/lab3/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# osc2022 -## Author - -| 學號 | GitHub 帳號 | 姓名 | Email | -| --- | ----------- | --- | --- | -|`309554042`| `JusticeLeee` | `李政毅` | franklp97531@gmail.com | - -## How to build - -```bash -./make.sh -``` -## How to run - -```bash -make run -``` -## How to burn it into pi3 -```bash -./rus.sh # write kernel to rpi3 through uart -sudo screen /dev/ttyUSB0 115200 -``` -## Note - -copy some string.h source for use strcmp \ No newline at end of file diff --git a/lab4/README.md b/lab4/README.md deleted file mode 100644 index 78ddcba99..000000000 --- a/lab4/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# osc2022 -## Author - -| 學號 | GitHub 帳號 | 姓名 | Email | -| --- | ----------- | --- | --- | -|`309554042`| `JusticeLeee` | `李政毅` | franklp97531@gmail.com | - -## How to build - -```bash -./make.sh -``` -## How to run - -```bash -make run -``` -## How to burn it into pi3 -```bash -./rus.sh # write kernel to rpi3 through uart -sudo screen /dev/ttyUSB0 115200 -``` -## Note - -copy some string.h source for use strcmp \ No newline at end of file diff --git a/lab5/README.md b/lab5/README.md deleted file mode 100644 index 78ddcba99..000000000 --- a/lab5/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# osc2022 -## Author - -| 學號 | GitHub 帳號 | 姓名 | Email | -| --- | ----------- | --- | --- | -|`309554042`| `JusticeLeee` | `李政毅` | franklp97531@gmail.com | - -## How to build - -```bash -./make.sh -``` -## How to run - -```bash -make run -``` -## How to burn it into pi3 -```bash -./rus.sh # write kernel to rpi3 through uart -sudo screen /dev/ttyUSB0 115200 -``` -## Note - -copy some string.h source for use strcmp \ No newline at end of file diff --git a/lab5/kernel/Makefile b/lab5/kernel/Makefile index d40a24e22..54fc6c2c5 100644 --- a/lab5/kernel/Makefile +++ b/lab5/kernel/Makefile @@ -37,11 +37,13 @@ kernel8.img: kernel8.elf $(OBJCOPY) $(OBJCOPYFLAGS) $(BUILD_DIR)/kernel8.elf $(BUILD_DIR)/kernel8.img run: - $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -display none -serial null -serial stdio -initrd initramfs.cpio + $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -display none -serial null -serial stdio -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb run1: - $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -display vnc=127.0.0.4:0 -serial null -serial stdio -initrd initramfs.cpio + killall -9 qemu-system-aarch64 + $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -display vnc=127.0.0.4:0 -serial null -serial stdio -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb debug: + killall -9 qemu-system-aarch64 $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -serial null -serial stdio -display none -S -s -initrd initramfs.cpio \ No newline at end of file diff --git a/lab5/kernel/include/dtb.h b/lab5/kernel/include/dtb.h new file mode 100644 index 000000000..f4dfc9163 --- /dev/null +++ b/lab5/kernel/include/dtb.h @@ -0,0 +1,38 @@ +#pragma once + +#include "utils.h" + +#define FDT_BEGIN_NODE (0x00000001) +#define FDT_END_NODE (0x00000002) +#define FDT_PROP (0x00000003) +#define FDT_NOP (0x00000004) +#define FDT_END (0x00000009) + +typedef struct { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +} fdt_header; + +void mailbox_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void gpio_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void rtx3080ti_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void default_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +int check_compatibility(uint64_t struct_addr, uint64_t strings_addr, + char *compatible_name); + +void dtb_print(int all); +void dtb_parse(uint64_t struct_addr, uint64_t strings_addr, + void (*callback)(uint64_t, uint64_t, int)); +uint64_t ignore_current_node(uint64_t struct_addr, uint64_t strings_addr); +uint64_t print_node(uint64_t struct_addr, uint64_t strings_addr, int depth); +uint64_t print_property(uint64_t struct_addr, uint64_t strings_addr, int depth); +uint32_t dtb_read_int(uint64_t addr_ptr); +// char *dtb_read_string(uint64_t *addr_ptr); \ No newline at end of file diff --git a/lab5/kernel/include/shell.h b/lab5/kernel/include/shell.h index 755059693..1f7075b10 100644 --- a/lab5/kernel/include/shell.h +++ b/lab5/kernel/include/shell.h @@ -27,5 +27,6 @@ void command_dma_test(); void command_thread_test1() ; void command_thread_test2() ; void command_thread_test3() ; +void command_thread_test4() ; void parse_command(char * buffer); void run_shell(); diff --git a/lab5/kernel/include/thread.h b/lab5/kernel/include/thread.h index 054301233..1b0a22a25 100644 --- a/lab5/kernel/include/thread.h +++ b/lab5/kernel/include/thread.h @@ -57,6 +57,7 @@ void foo(); void thread_test1(); void thread_test2(); void thread_test3(); +void thread_test4(); void thread_init(); thread_info *thread_create(void (*func)()); diff --git a/lab5/kernel/include/utils.h b/lab5/kernel/include/utils.h index b8d3b0a95..085a90b13 100644 --- a/lab5/kernel/include/utils.h +++ b/lab5/kernel/include/utils.h @@ -1,8 +1,8 @@ #ifndef _UTILS_H_ #define _UTILS_H_ #include -uint8_t hex_to_int64(char*); -uint64_t hex_to_int8(char); +uint64_t hex_to_int64(char* num); +uint8_t hex_to_int8(char hex); uint64_t hex2int(char *hex, int len); uint64_t align_up(uint64_t addr, uint64_t alignment); uint64_t align_up_exp(uint64_t n); @@ -11,5 +11,5 @@ uint64_t align_up_exp(uint64_t n); #define gb ((uint64_t)0x40000000) uint64_t log2(uint64_t num); void delay(int num); - +uint32_t be2le(uint32_t x); #endif diff --git a/lab5/kernel/src/dtb.c b/lab5/kernel/src/dtb.c new file mode 100644 index 000000000..e9461b191 --- /dev/null +++ b/lab5/kernel/src/dtb.c @@ -0,0 +1,252 @@ +#include "dtb.h" + +#include "printf.h" +#include "string.h" +#include "utils.h" + +void mailbox_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + if (check_compatibility(struct_addr, strings_addr, "brcm,bcm2835-mbox") == 0) + return; + print_node(struct_addr, strings_addr, depth); +} + +void gpio_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + if (check_compatibility(struct_addr, strings_addr, "brcm,bcm2835-gpio") == 0) + return; + print_node(struct_addr, strings_addr, depth); +} + +void rtx3080ti_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + if (check_compatibility(struct_addr, strings_addr, "rtx3080ti") == 0) return; + print_node(struct_addr, strings_addr, depth); +} + +void default_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + print_node(struct_addr, strings_addr, depth); +} + +int check_compatibility(uint64_t struct_addr, uint64_t strings_addr, + char *compatible_name) { + char *name = (char *)(struct_addr); + struct_addr += strlen(name) + 1; + struct_addr = align_up(struct_addr, 4); + + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_PROP) { + uint32_t len = dtb_read_int(struct_addr); + len = be2le(len); + struct_addr += 4; + uint32_t nameoff = dtb_read_int(struct_addr); + nameoff = be2le(nameoff); + struct_addr += 4; + char *property = (char *)(strings_addr + nameoff); + + if (strcmp(property, "compatible") == 0) { + uint64_t end = struct_addr + len; + while (struct_addr < end) { + char *string = (char *)struct_addr; + struct_addr += strlen(string) + 1; + if (strcmp(string, compatible_name) == 0) return 1; + } + return 0; + } else { + struct_addr += len; + struct_addr = align_up(struct_addr, 4); + } + } else if (token == FDT_NOP) { + continue; + } else { + break; + } + } + return 0; +} + +void dtb_print(int all) { + uint64_t dtb_addr = *((uint64_t *)0x9000000); + printf("dtb_addr = %x\n",dtb_addr); + fdt_header *header = (fdt_header *)dtb_addr; + uint64_t struct_addr = dtb_addr + be2le(header->off_dt_struct); + uint64_t strings_addr = dtb_addr + be2le(header->off_dt_strings); + + if (all) { + dtb_parse(struct_addr, strings_addr, default_probe); + } else { + printf("\ndevice for mailbox driver function: \n"); + dtb_parse(struct_addr, strings_addr, mailbox_probe); + printf("\ndevice for gpio driver function: \n"); + dtb_parse(struct_addr, strings_addr, gpio_probe); + printf("\ndevice for rtx3080ti driver function: \n"); + dtb_parse(struct_addr, strings_addr, rtx3080ti_probe); + } +} + +void dtb_parse(uint64_t struct_addr, uint64_t strings_addr, + void (*callback)(uint64_t, uint64_t, int)) { + int depth = 0; + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + callback(struct_addr, strings_addr, depth); + struct_addr = ignore_current_node(struct_addr, strings_addr); + depth++; + } else if (token == FDT_END_NODE) { + depth--; + } else if (token == FDT_NOP) { + continue; + } else if (token == FDT_END) { + break; + } + } +} + +uint64_t ignore_current_node(uint64_t struct_addr, uint64_t strings_addr) { + char *name = (char *)(struct_addr); + struct_addr += strlen(name) + 1; + struct_addr = align_up(struct_addr, 4); + + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_END_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_PROP) { + uint32_t len = dtb_read_int(struct_addr); + len = be2le(len); + struct_addr += 4; + uint32_t nameoff = dtb_read_int(struct_addr); + nameoff = be2le(nameoff); + struct_addr += 4; + struct_addr += len; + struct_addr = align_up(struct_addr, 4); + } else if (token == FDT_NOP) { + continue; + } + } + return struct_addr; +} + +uint64_t print_node(uint64_t struct_addr, uint64_t strings_addr, int depth) { + char *name = (char *)(struct_addr); + struct_addr += strlen(name) + 1; + struct_addr = align_up(struct_addr, 4); + for (int i = 0; i < depth; i++) printf(" "); + printf("node: %s\n", name); + + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + break; + } else if (token == FDT_END_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_PROP) { + struct_addr = print_property(struct_addr, strings_addr, depth + 1); + } else if (token == FDT_NOP) { + continue; + } + } + return struct_addr; +} + +uint64_t print_property(uint64_t struct_addr, uint64_t strings_addr, + int depth) { + uint32_t len = dtb_read_int(struct_addr); + len = be2le(len); + struct_addr += 4; + uint32_t nameoff = dtb_read_int(struct_addr); + nameoff = be2le(nameoff); + struct_addr += 4; + char *property = (char *)(strings_addr + nameoff); + + int value_type = 0; + char *is_u32[] = {"phandle", "#address-cells", "#size-cells", "virtual-reg", + "interrupt-parent"}; + char *is_string[] = {"compatible", "model", "status", "name", "device_type"}; + + for (int i = 0; i < sizeof(is_u32) / sizeof(is_u32[0]); i++) { + if (strcmp(property, is_u32[i]) == 0) { + value_type = 1; + break; + } + } + for (int i = 0; i < sizeof(is_string) / sizeof(is_string[0]); i++) { + if (strcmp(property, is_string[i]) == 0) { + value_type = 2; + break; + } + } + + for (int i = 0; i < depth; i++) printf(" "); + printf("%s = ", property); + + // hex, e.g. <0x4600 0x100> + if (value_type == 0) { + int count = 0; + printf("<"); + for (uint32_t i = 0; i < len; i += 4) { + if (count > 0) printf(" "); + count++; + uint32_t num = dtb_read_int(struct_addr); + num = be2le(num); + struct_addr += 4; + printf("0x%x", num); + } + printf(">"); + } + // int, e.g. <1> + if (value_type == 1) { + uint32_t num = dtb_read_int(struct_addr); + num = be2le(num); + struct_addr += 4; + printf("<%d>", num); + } + // string or string list, e.g. "fsl,MPC8349EMITX" or "fsl,mpc8641", "ns16550" + if (value_type == 2) { + int count = 0; + uint64_t end = struct_addr + len; + + while (struct_addr < end) { + if (count > 0) printf(", "); + count++; + char *string = (char *)struct_addr; + struct_addr += strlen(string) + 1; + printf("\"%s\"", string); + } + } + printf("\n"); + + struct_addr = align_up(struct_addr, 4); + return struct_addr; +} + +uint32_t dtb_read_int(uint64_t addr_ptr) { + char *base = (char *)(addr_ptr); + uint32_t value = 0; + for (int i = 3; i >= 0; i--) { + value = (value << 8) | (*(base + i) & 0xFF); + } + return value; +} + +// char *dtb_read_string(uint64_t addr_ptr) { +// char *base = (char *)(addr_ptr); +// char *string_start = base; +// return string_start; +// } \ No newline at end of file diff --git a/lab5/kernel/src/exception.c b/lab5/kernel/src/exception.c index 286320ce5..3addfcadb 100644 --- a/lab5/kernel/src/exception.c +++ b/lab5/kernel/src/exception.c @@ -26,6 +26,7 @@ void sync_handler_currentEL_ELx() { } void sync_handler_lowerEL_64(uint64_t sp) { + // printf("sync_handler_lowerEL_64 sp : %x\n",sp); uint64_t spsr_el1, elr_el1, esr_el1; asm volatile("mrs %0, spsr_el1" : "=r"(spsr_el1)); asm volatile("mrs %0, elr_el1" : "=r"(elr_el1)); @@ -37,6 +38,7 @@ void sync_handler_lowerEL_64(uint64_t sp) { uint32_t ec = (esr_el1 >> 26) & 0x3f; // printf("EC: %x\n", ec); if (ec == 0b010101) { // SVC instruction + // printf("pid = %d, ",get_current()->pid); uint64_t iss; asm volatile("mov %0, x8" : "=r"(iss)); // printf("syscall number: %d\n", iss); @@ -46,6 +48,7 @@ void sync_handler_lowerEL_64(uint64_t sp) { uint32_t pid = get_current()->pid; trap_frame->x[0] = pid; } else if (iss == 1) { // uartread + // printf("[read]\n"); disable_uart_interrupt(); enable_interrupt(); char *str = (char *)(trap_frame->x[0]); @@ -53,6 +56,7 @@ void sync_handler_lowerEL_64(uint64_t sp) { size = uart_gets(str, size); trap_frame->x[0] = size; } else if (iss == 2) { // uartwrite + // printf("[write]\n"); char *str = (char *)(trap_frame->x[0]); trap_frame->x[0] = uart_write(str,trap_frame->x[1]); } else if (iss == 3) { // exec @@ -60,10 +64,12 @@ void sync_handler_lowerEL_64(uint64_t sp) { const char **argv = (const char **)trap_frame->x[1]; exec(program_name, argv); } else if (iss == 4) { // fork + // printf("[fork]\n"); fork(sp); } else if (iss == 5) { // exit exit(); } else if (iss == 6) { // mbox_call + // printf("[mbox_call]\n"); trap_frame->x[0] = mbox_call(trap_frame->x[0],(unsigned int *)trap_frame->x[1]); } else if (iss == 7) { // kill kill((int)trap_frame->x[0]); @@ -71,6 +77,7 @@ void sync_handler_lowerEL_64(uint64_t sp) { } } + void irq_handler_currentEL_ELx() { // printf("====irq_handler_currentEL_ELx=====\n"); diff --git a/lab5/kernel/src/linker.ld b/lab5/kernel/src/linker.ld index 1352bfb14..ef09ab120 100644 --- a/lab5/kernel/src/linker.ld +++ b/lab5/kernel/src/linker.ld @@ -41,4 +41,4 @@ SECTIONS /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } } -__bss_size = (__bss_end - __bss_start)>>3; +__bss_size = (__bss_end - __bss_start)>>3; \ No newline at end of file diff --git a/lab5/kernel/src/shell.c b/lab5/kernel/src/shell.c index 017648d12..9953a2d6f 100644 --- a/lab5/kernel/src/shell.c +++ b/lab5/kernel/src/shell.c @@ -9,6 +9,7 @@ #include "utils.h" #include "thread.h" #include "printf.h" +#include "dtb.h" void clean_buffer(char * buffer, int buffer_len) { @@ -23,6 +24,8 @@ void command_help() uart_puts("hello\t\t: print Hello World!\n"); uart_puts("reboot\t\t: reboot the device\n"); uart_puts("mailbox\t\t: show information through mailbox\n"); + uart_puts("dtb\t\t: parse device tree message\n"); + uart_puts("dtb all\t\t: parse device tree message\n"); uart_puts("ls\t\t: show all files\n"); uart_puts("cat\t\t: show file info\n"); uart_puts("test\t\t: test simple allocator\n"); @@ -178,6 +181,11 @@ void command_thread_test2() { void command_thread_test3() { thread_test3(); } +void command_thread_test4() { + thread_test4(); +} +void command_dtb_print(int all) { dtb_print(all); } + void parse_command(char * buffer) { if ( !strcmp(buffer, "help")) command_help(); @@ -193,9 +201,12 @@ void parse_command(char * buffer) else if ( !strncmp(buffer, "setTimeout", 10)) command_set_timeout(&buffer[11]); else if ( !strcmp(buffer, "buddy test")) command_buddy_test(); else if ( !strcmp(buffer, "dma test")) command_dma_test(); + else if ( !strcmp(buffer, "dtb")) command_dtb_print(0); + else if ( !strcmp(buffer, "dtb all")) command_dtb_print(1); else if ( !strcmp(buffer, "t1")) command_thread_test1(); else if ( !strcmp(buffer, "t2")) command_thread_test2(); else if ( !strcmp(buffer, "t3")) command_thread_test3(); + else if ( !strcmp(buffer, "t4")) command_thread_test4(); else command_not_found(buffer); } diff --git a/lab5/kernel/src/start.S b/lab5/kernel/src/start.S index 018a65503..ccc0e40fb 100644 --- a/lab5/kernel/src/start.S +++ b/lab5/kernel/src/start.S @@ -36,6 +36,10 @@ _start: master: // cpu id == 0 + // save dtb loading address + ldr x1, =0x9000000 + str x0, [x1] + bl from_el2_to_el1 bl set_exception_vector_table diff --git a/lab5/kernel/src/thread.c b/lab5/kernel/src/thread.c index 986052186..68a0cbcdc 100644 --- a/lab5/kernel/src/thread.c +++ b/lab5/kernel/src/thread.c @@ -17,36 +17,56 @@ void foo() { return; } -void thread_test1() { - thread_info *idle_t = thread_create(0); - asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); - for (int i = 0; i < 5; ++i) { - thread_create(foo); - } - idle(); +void user_test1() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("my_test", argv); } void user_test2() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("my_test2", argv); +} +void user_test3() { const char *argv[] = {"argv_test", "-o", "arg2", 0}; exec("fork_test", argv); } -void thread_test2() { +void user_test4() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("syscall.img", argv); +} + +void user_test5() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("vm.img", argv); +} + +void thread_test1() { // thread test thread_info *idle_t = thread_create(0); asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test1); thread_create(user_test2); idle(); } -void user_test3() { - const char *argv[] = {"argv_test", "-o", "arg2", 0}; - exec("syscall.img", argv); +void thread_test2() { // fork test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test3); + idle(); } -void thread_test3() { +void thread_test3() { //vedio player1 test thread_info *idle_t = thread_create(0); asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); - thread_create(user_test3); + thread_create(user_test4); + idle(); +} + +void thread_test4() { //vedio player1 test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test5); idle(); } @@ -63,7 +83,7 @@ thread_info *thread_create(void (*func)()) { thread->status = THREAD_READY; thread->next = 0; thread->kernel_stack_base = (uint64_t)malloc(STACK_SIZE); - thread->user_stack_base = 0; + thread->user_stack_base = (uint64_t)malloc(STACK_SIZE); thread->user_program_base = USER_PROGRAM_BASE + thread->pid * USER_PROGRAM_SIZE; thread->context.fp = thread->kernel_stack_base + STACK_SIZE; @@ -148,9 +168,7 @@ void kill_zombies() { void exec(const char *program_name, const char **argv) { thread_info *cur = get_current(); - if (cur->user_stack_base == 0) { - cur->user_stack_base = (uint64_t)malloc(STACK_SIZE); - } + uint64_t user_sp = cur->user_stack_base + STACK_SIZE; cur->user_program_size = cpio_load_user_program(program_name, cur->user_program_base); // printf("cur->pid = %d, cur->user_program_base = %x\n",cur->pid,cur->user_program_base); diff --git a/lab5/kernel/src/utils.c b/lab5/kernel/src/utils.c index d5547d08b..8047ee2c7 100644 --- a/lab5/kernel/src/utils.c +++ b/lab5/kernel/src/utils.c @@ -1,5 +1,6 @@ -typedef unsigned long long int uint64_t; -typedef unsigned char uint8_t; +// typedef unsigned long long int uint64_t; +// typedef unsigned char uint8_t; +#include "utils.h" uint8_t hex_to_int8(char hex){ if(hex >= '0' && hex <= '9') @@ -62,4 +63,9 @@ uint64_t hex2int(char *hex, int len) { val = (val << 4) | (byte & 0xF); } return val; +} + +uint32_t be2le(uint32_t x) { + return (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) | + (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); } \ No newline at end of file diff --git a/lab5/qemu_run.sh b/lab5/qemu_run.sh new file mode 100755 index 000000000..4673212bd --- /dev/null +++ b/lab5/qemu_run.sh @@ -0,0 +1,4 @@ +# sudo chmod 777 /dev/ttyUSB0 +# python3 ./script/send_file.py -s bootloader.img +# python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/ttyUSB0 +python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/pts/14 diff --git a/lab6/bootloader/Makefile b/lab6/bootloader/Makefile new file mode 100644 index 000000000..cff2e3c2a --- /dev/null +++ b/lab6/bootloader/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) 2018 bzt (bztsrc@github) +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, copy, +# modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +# + +CFILE = $(wildcard *.c) +ASMFILE = $(wildcard *.S) +OBJS = $(CFILE:.c=_c.o) +OBJS += $(ASMFILE:.S=_s.o) +CFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -fno-stack-protector -Iinclude -Iinclude + +all: kernel8.img + +%_s.o: %.S + aarch64-elf-gcc $(CFLAGS) -c $< -o $@ + +%_c.o: %.c + aarch64-elf-gcc $(CFLAGS) -c $< -o $@ + +kernel8.img: $(OBJS) + aarch64-elf-ld -nostdlib -nostartfiles $(OBJS) -T link.ld -o bootloader.elf + aarch64-elf-objcopy -O binary bootloader.elf bootloader.img + +clean: + rm kernel8.elf *.o >/dev/null 2>/dev/null || true + +run: + qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial null -serial stdio diff --git a/lab6/bootloader/bootloader.elf b/lab6/bootloader/bootloader.elf new file mode 100755 index 000000000..74f2d52e7 Binary files /dev/null and b/lab6/bootloader/bootloader.elf differ diff --git a/lab6/bootloader/bootloader.img b/lab6/bootloader/bootloader.img new file mode 100755 index 000000000..e777a0053 Binary files /dev/null and b/lab6/bootloader/bootloader.img differ diff --git a/lab6/bootloader/include/mini_uart.h b/lab6/bootloader/include/mini_uart.h new file mode 100644 index 000000000..aebc2c5a2 --- /dev/null +++ b/lab6/bootloader/include/mini_uart.h @@ -0,0 +1,9 @@ +#ifndef _MINI_UART_H +#define _MINI_UART_H + +void uart_init(void); +char uart_getc(void); +void uart_putc(char c); +void uart_puts(char* str); + +#endif \ No newline at end of file diff --git a/lab6/bootloader/include/mm.h b/lab6/bootloader/include/mm.h new file mode 100644 index 000000000..119624a2b --- /dev/null +++ b/lab6/bootloader/include/mm.h @@ -0,0 +1,17 @@ +#ifndef _MM_H +#define _MM_H + +#define PAGE_SHIFT 12 +#define TABLE_SHIFT 9 +#define SECTION_SHIFT (PAGE_SHIFT + TABLE_SHIFT) + +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define SECTION_SIZE (1 << SECTION_SHIFT) + +#define LOW_MEMORY (2 * SECTION_SIZE) + +#ifndef __ASSEMBLER__ +void memzero(unsigned long src, unsigned long n); +#endif + +#endif \ No newline at end of file diff --git a/lab6/bootloader/include/peripherals/base.h b/lab6/bootloader/include/peripherals/base.h new file mode 100644 index 000000000..d7eb1f9b5 --- /dev/null +++ b/lab6/bootloader/include/peripherals/base.h @@ -0,0 +1,6 @@ +#ifndef _PER_BASE_H_ +#define _PER_BASE_H_ + +#define PHY_BASE_ADDR 0x3F000000 + +#endif \ No newline at end of file diff --git a/lab6/bootloader/include/peripherals/gpio.h b/lab6/bootloader/include/peripherals/gpio.h new file mode 100644 index 000000000..1132dae95 --- /dev/null +++ b/lab6/bootloader/include/peripherals/gpio.h @@ -0,0 +1,12 @@ +#ifndef _PER_GPIO_H +#define _PER_GPIO_H + +#include "peripherals/base.h" + +#define GPFSEL1 (PHY_BASE_ADDR + 0x00200004) +#define GPSET0 (PHY_BASE_ADDR + 0x0020001C) +#define GPCLR0 (PHY_BASE_ADDR + 0x00200028) +#define GPPUD (PHY_BASE_ADDR + 0x00200094) +#define GPPUDCLK0 (PHY_BASE_ADDR + 0x00200098) + +#endif \ No newline at end of file diff --git a/lab6/bootloader/include/peripherals/mini_uart.h b/lab6/bootloader/include/peripherals/mini_uart.h new file mode 100644 index 000000000..c08d34831 --- /dev/null +++ b/lab6/bootloader/include/peripherals/mini_uart.h @@ -0,0 +1,18 @@ +#ifndef _PER_MINI_UART_H_ +#define _PER_MINI_UART_H_ + +#include "peripherals/base.h" +#define AUX_ENABLES (PHY_BASE_ADDR + 0x00215004) +#define AUX_MU_IO_REG (PHY_BASE_ADDR + 0x00215040) +#define AUX_MU_IER_REG (PHY_BASE_ADDR + 0x00215044) +#define AUX_MU_IIR_REG (PHY_BASE_ADDR + 0x00215048) +#define AUX_MU_LCR_REG (PHY_BASE_ADDR + 0x0021504C) +#define AUX_MU_MCR_REG (PHY_BASE_ADDR + 0x00215050) +#define AUX_MU_LSR_REG (PHY_BASE_ADDR + 0x00215054) +#define AUX_MU_MSR_REG (PHY_BASE_ADDR + 0x00215058) +#define AUX_MU_SCRATCH (PHY_BASE_ADDR + 0x0021505C) +#define AUX_MU_CNTL_REG (PHY_BASE_ADDR + 0x00215060) +#define AUX_MU_STAT_REG (PHY_BASE_ADDR + 0x00215064) +#define AUX_MU_BAUD_REG (PHY_BASE_ADDR + 0x00215068) + +#endif \ No newline at end of file diff --git a/lab6/bootloader/include/shell.h b/lab6/bootloader/include/shell.h new file mode 100644 index 000000000..d588b1de9 --- /dev/null +++ b/lab6/bootloader/include/shell.h @@ -0,0 +1,26 @@ +#ifndef _SHELL_H +#define _SHELL_H + +void buffer_clear(); +void execute_command(char *); +void init_shell(); + +void print_input_prompt(); +void get_input(); + +void del_key(); +void left_key(); +void right_key(); +void up_key(); +void down_key(); + +void simple_shell(); + +void shell_hello(); +void shell_help(); +void shell_reboot(); +void shell_boot_uart(); + +void shell_ls(); + +#endif \ No newline at end of file diff --git a/lab6/bootloader/include/stdint.h b/lab6/bootloader/include/stdint.h new file mode 100644 index 000000000..ebc26e483 --- /dev/null +++ b/lab6/bootloader/include/stdint.h @@ -0,0 +1,18 @@ +#ifndef _STDINT_H +#define _STDINT_H + +typedef unsigned long long int uint64_t; +typedef signed long long int int64_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +typedef unsigned short int uint16_t; +typedef signed short int int16_t; + +typedef unsigned char uint8_t; +typedef signed char int8_t; + +uint8_t hex_to_int64(char*); +uint64_t hex_to_int8(char); +#endif \ No newline at end of file diff --git a/lab6/bootloader/include/str_tool.h b/lab6/bootloader/include/str_tool.h new file mode 100644 index 000000000..3d5018e36 --- /dev/null +++ b/lab6/bootloader/include/str_tool.h @@ -0,0 +1,24 @@ +#ifndef _STR_TOOL_H +#define _STR_TOOL_H +#include "stdint.h" + +typedef struct { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} cpio_newc_header; + +int strcmp(char*, char*); +char* itoa(int64_t, int); +#endif \ No newline at end of file diff --git a/lab6/bootloader/include/utils.h b/lab6/bootloader/include/utils.h new file mode 100644 index 000000000..99dfeecc6 --- /dev/null +++ b/lab6/bootloader/include/utils.h @@ -0,0 +1,8 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +void delay(unsigned long); +void put32(unsigned long, unsigned int); +unsigned int get32(unsigned long); + +#endif \ No newline at end of file diff --git a/lab6/bootloader/link.ld b/lab6/bootloader/link.ld new file mode 100644 index 000000000..dfbf24cf2 --- /dev/null +++ b/lab6/bootloader/link.ld @@ -0,0 +1,13 @@ +SECTIONS +{ + . = 0x50000; + .text : { KEEP(*(.text.boot)) *(.text) } + .rodata : { *(.rodata) } + .data : { *(.data) } + + . = ALIGN(0x8); + bss_begin = .; + .bss : { *(.bss*) } + bss_end = .; + _end = .; +} diff --git a/lab6/bootloader/main.c b/lab6/bootloader/main.c new file mode 100644 index 000000000..46afb4dfb --- /dev/null +++ b/lab6/bootloader/main.c @@ -0,0 +1,31 @@ +#include "mini_uart.h" +#include "utils.h" +#include "stdint.h" + +union large_int_by_byte{ + uint8_t int_by_byte[8]; + uint64_t larg_int; +}; + +void boot_main(){ + uart_init(); + + union large_int_by_byte program; + volatile uint8_t *program_addr = (volatile uint8_t *)0x80000; + + // read dirty message until end + while(1) { + uint8_t data; + data = uart_getc(); + if(data==4)break; + } + + // read kernel size + for(int i=0; i<8; i++) + program.int_by_byte[i] = uart_getc(); + + for(uint64_t offset=0; offset= '0' && hex <= '9') + return hex-'0'; + else if(hex >= 'A' && hex <= 'Z') + return hex-'A'+10; + else if(hex >= 'a' && hex <= 'z') + return hex-'a'+10; + else + return -1; +} + +uint64_t hex_to_int64(char* num){ + uint64_t res=0; + for(int i=0; i<8; i++){ + res = (res<<4) + hex_to_int8(num[i]); + } + return res; +} \ No newline at end of file diff --git a/lab6/bootloader/str_tool.c b/lab6/bootloader/str_tool.c new file mode 100644 index 000000000..cb955f297 --- /dev/null +++ b/lab6/bootloader/str_tool.c @@ -0,0 +1,23 @@ +#include "stdint.h" + +int strcmp(char *s1, char *s2){ + while(*s1!='\0' && *s2!='\0' && *s1==*s2){ + s1 += 1; + s2 += 1; + } + return *s1 - *s2; +} + +char* itoa(int64_t val, int base){ + static char buf[32] = {0}; + int i = 30; + if (val == 0) { + buf[i] = '0'; + return &buf[i]; + } + + for (; val && i; --i, val /= base) + buf[i] = "0123456789abcdef"[val % base]; + + return &buf[i + 1]; +} \ No newline at end of file diff --git a/lab6/bootloader/utils.S b/lab6/bootloader/utils.S new file mode 100644 index 000000000..e735f1dc7 --- /dev/null +++ b/lab6/bootloader/utils.S @@ -0,0 +1,15 @@ +.globl put32 +put32: + str w1, [x0] + ret + +.globl get32 +get32: + ldr w0, [x0] + ret + +.globl delay +delay: + subs x0, x0, #1 + bne delay + ret \ No newline at end of file diff --git a/lab6/bootloader/utils/mini_uart.c b/lab6/bootloader/utils/mini_uart.c new file mode 100644 index 000000000..46ca9cfe0 --- /dev/null +++ b/lab6/bootloader/utils/mini_uart.c @@ -0,0 +1,47 @@ +#include "utils.h" +#include "peripherals/gpio.h" +#include "peripherals/mini_uart.h" + +void uart_init(){ + unsigned int selector; + + selector = get32(GPFSEL1); + selector &= ~(7<<12); // clean gpio 14 + selector |= 2<<12; // set alt5 at gpio14 + selector &= ~(7<<15); // clean gpio 15 + selector |= 2<<15; // set alt5 at gpio 15 + put32(GPFSEL1, selector); + + put32(GPPUD, 0); // disable pull-up/down + delay(150); // wait 150 cycles + put32(GPPUDCLK0, (1<<14)|(1<<15)); // only modify GPIO 14 and 15 + delay(150); + put32(GPPUDCLK0, 0); // remove the clock + + put32(AUX_ENABLES, 1); // enable mini UART + put32(AUX_MU_CNTL_REG, 0); // Disable transmitter and receiver during configuration + put32(AUX_MU_IER_REG, 0); // Disable interrupt + put32(AUX_MU_LCR_REG, 3); // Set the data size to 8 bit + put32(AUX_MU_MCR_REG, 0); // Don’t need auto flow control + put32(AUX_MU_BAUD_REG, 270); // Set baud rate to 115200 + + put32(AUX_MU_IIR_REG, 6); // No FIFO + put32(AUX_MU_CNTL_REG, 3); // Enable the transmitter and receiver +} + +void uart_putc(char c){ + while(!(get32(AUX_MU_LSR_REG)&0x20)); + put32(AUX_MU_IO_REG, c); +} + +char uart_getc(void){ + while(!(get32(AUX_MU_LSR_REG)&0x01)); + return get32(AUX_MU_IO_REG); +} + +void uart_puts(char* str){ + while(*str){ + uart_putc(*str); + str += 1; + } +} \ No newline at end of file diff --git a/lab6/bootloader/utils/mm.S b/lab6/bootloader/utils/mm.S new file mode 100644 index 000000000..f9b279e14 --- /dev/null +++ b/lab6/bootloader/utils/mm.S @@ -0,0 +1,6 @@ +.globl memzero +memzero: + str xzr, [x0], #8 + subs x1, x1, #8 + b.gt memzero + ret \ No newline at end of file diff --git a/lab6/bootloader/utils/stdint.c b/lab6/bootloader/utils/stdint.c new file mode 100644 index 000000000..c41cc43ea --- /dev/null +++ b/lab6/bootloader/utils/stdint.c @@ -0,0 +1,21 @@ +typedef unsigned long long int uint64_t; +typedef unsigned char uint8_t; + +uint8_t hex_to_int8(char hex){ + if(hex >= '0' && hex <= '9') + return hex-'0'; + else if(hex >= 'A' && hex <= 'Z') + return hex-'A'+10; + else if(hex >= 'a' && hex <= 'z') + return hex-'a'+10; + else + return -1; +} + +uint64_t hex_to_int64(char* num){ + uint64_t res=0; + for(int i=0; i<8; i++){ + res = (res<<4) + hex_to_int8(num[i]); + } + return res; +} \ No newline at end of file diff --git a/lab6/bootloader/utils/str_tool.c b/lab6/bootloader/utils/str_tool.c new file mode 100644 index 000000000..cb955f297 --- /dev/null +++ b/lab6/bootloader/utils/str_tool.c @@ -0,0 +1,23 @@ +#include "stdint.h" + +int strcmp(char *s1, char *s2){ + while(*s1!='\0' && *s2!='\0' && *s1==*s2){ + s1 += 1; + s2 += 1; + } + return *s1 - *s2; +} + +char* itoa(int64_t val, int base){ + static char buf[32] = {0}; + int i = 30; + if (val == 0) { + buf[i] = '0'; + return &buf[i]; + } + + for (; val && i; --i, val /= base) + buf[i] = "0123456789abcdef"[val % base]; + + return &buf[i + 1]; +} \ No newline at end of file diff --git a/lab6/bootloader/utils/utils.S b/lab6/bootloader/utils/utils.S new file mode 100644 index 000000000..e735f1dc7 --- /dev/null +++ b/lab6/bootloader/utils/utils.S @@ -0,0 +1,15 @@ +.globl put32 +put32: + str w1, [x0] + ret + +.globl get32 +get32: + ldr w0, [x0] + ret + +.globl delay +delay: + subs x0, x0, #1 + bne delay + ret \ No newline at end of file diff --git a/lab6/config.txt b/lab6/config.txt new file mode 100644 index 000000000..261480683 --- /dev/null +++ b/lab6/config.txt @@ -0,0 +1,4 @@ +kernel_address=0x60000 +kernel=bootloader.img +arm_64bit=1 +initramfs initramfs.cpio 0x8000000 \ No newline at end of file diff --git a/lab6/kernel/Makefile b/lab6/kernel/Makefile new file mode 100644 index 000000000..df9e3c8df --- /dev/null +++ b/lab6/kernel/Makefile @@ -0,0 +1,49 @@ +CC = aarch64-linux-gnu-gcc +CFLAGS = -Iinclude -Wall -nostdlib -nostartfiles -ffreestanding +# ASMFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJCOPYFLAGS = -O binary + +QEMU = qemu-system-aarch64 + +BUILD_DIR = build +SRC_DIR = src + +all: initramfs.cpio kernel8.img + +initramfs.cpio: + cd rootfs; find . | cpio -o -H newc > ../initramfs.cpio; cd ..; + +clean: + rm $(BUILD_DIR)/* initramfs.cpio + +$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c + mkdir -p $(@D) + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S + $(CC) $(CFLAGS) -c $< -o $@ + +C_FILES = $(wildcard $(SRC_DIR)/*.c) +ASM_FILES = $(wildcard $(SRC_DIR)/*.S) +OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o) +OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o) + +kernel8.elf: $(SRC_DIR)/linker.ld $(OBJ_FILES) + $(LD) -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf $(OBJ_FILES) + +kernel8.img: kernel8.elf + $(OBJCOPY) $(OBJCOPYFLAGS) $(BUILD_DIR)/kernel8.elf $(BUILD_DIR)/kernel8.img + +run: + $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -display none -serial null -serial stdio -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + +run1: + killall -9 qemu-system-aarch64 + $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -display vnc=127.0.0.4:0 -serial null -serial stdio -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + + +debug: + killall -9 qemu-system-aarch64 + $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -serial null -serial stdio -display none -S -s -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb \ No newline at end of file diff --git a/lab6/kernel/gdb_file b/lab6/kernel/gdb_file new file mode 100644 index 000000000..8e9744669 --- /dev/null +++ b/lab6/kernel/gdb_file @@ -0,0 +1,2 @@ +file build/kernel8.elf +target remote :1234 \ No newline at end of file diff --git a/lab6/kernel/include/alloc.h b/lab6/kernel/include/alloc.h new file mode 100644 index 000000000..9c92ef0c0 --- /dev/null +++ b/lab6/kernel/include/alloc.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include "utils.h" +#include "mmu.h" + +#define PAGE_BASE_ADDR ((uint64_t)(KVA + 0x10000000)) +#define PAGE_END_ADDR ((uint64_t)(KVA + 0x20000000)) +#define PAGE_SIZE ((uint64_t)(4 * kb)) +#define MAX_PAGE_NUM \ + ((uint64_t)((PAGE_END_ADDR - PAGE_BASE_ADDR) / PAGE_SIZE)) // 65536 +#define MAX_FRAME_ORDER 16 // 2^16 = 65536 +#define FRAME_LIST_NUM (MAX_FRAME_ORDER + 1) + +typedef struct PageFrame { + int id; + int order; + int is_allocated; + uint64_t addr; + struct PageFrame *next; +} page_frame; + +typedef struct DMAHeader { + uint64_t total_size; + uint64_t used_size; + int is_allocated; + page_frame *frame_ptr; + struct DMAHeader *prev, *next; +} dma_header; + +page_frame frames[MAX_PAGE_NUM]; +page_frame *free_frame_lists[FRAME_LIST_NUM], *used_frame_lists[FRAME_LIST_NUM]; + +dma_header *free_dma_list; + +void buddy_init(); +void buddy_test(); +page_frame *buddy_allocate(uint64_t size); +void buddy_free(page_frame *frame); +void buddy_unlink(int index, int type); +void print_frame_lists(); +void dma_test(); +void *malloc(uint64_t size); +void free(void *ptr); +void print_dma_list(); diff --git a/lab6/kernel/include/cpio.h b/lab6/kernel/include/cpio.h new file mode 100644 index 000000000..f239b5b02 --- /dev/null +++ b/lab6/kernel/include/cpio.h @@ -0,0 +1,29 @@ +#pragma once +#include +#include "mmu.h" + +#define RAMFS_ADDR (KVA + 0x8000000) +#define CPIO_MAGIC "070701" +#define CPIO_END "TRAILER!!!" + +typedef struct { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} cpio_newc_header; + +void cpio_ls(); +void cpio_cat(char *filename); +uint32_t cpio_load_user_program(const char *target_program, + uint64_t target_addr); \ No newline at end of file diff --git a/lab6/kernel/include/delays.h b/lab6/kernel/include/delays.h new file mode 100644 index 000000000..ebbeb94ce --- /dev/null +++ b/lab6/kernel/include/delays.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +void wait_cycles(unsigned int n); +void wait_msec(unsigned int n); +unsigned long get_system_timer(); +void wait_msec_st(unsigned int n); diff --git a/lab6/kernel/include/dtb.h b/lab6/kernel/include/dtb.h new file mode 100644 index 000000000..f4dfc9163 --- /dev/null +++ b/lab6/kernel/include/dtb.h @@ -0,0 +1,38 @@ +#pragma once + +#include "utils.h" + +#define FDT_BEGIN_NODE (0x00000001) +#define FDT_END_NODE (0x00000002) +#define FDT_PROP (0x00000003) +#define FDT_NOP (0x00000004) +#define FDT_END (0x00000009) + +typedef struct { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +} fdt_header; + +void mailbox_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void gpio_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void rtx3080ti_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void default_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +int check_compatibility(uint64_t struct_addr, uint64_t strings_addr, + char *compatible_name); + +void dtb_print(int all); +void dtb_parse(uint64_t struct_addr, uint64_t strings_addr, + void (*callback)(uint64_t, uint64_t, int)); +uint64_t ignore_current_node(uint64_t struct_addr, uint64_t strings_addr); +uint64_t print_node(uint64_t struct_addr, uint64_t strings_addr, int depth); +uint64_t print_property(uint64_t struct_addr, uint64_t strings_addr, int depth); +uint32_t dtb_read_int(uint64_t addr_ptr); +// char *dtb_read_string(uint64_t *addr_ptr); \ No newline at end of file diff --git a/lab6/kernel/include/exception.h b/lab6/kernel/include/exception.h new file mode 100644 index 000000000..3d916cf25 --- /dev/null +++ b/lab6/kernel/include/exception.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include "gpio.h" +#include "utils.h" +#include "mmu.h" + +#define CORE0_IRQ_SOURCE ((volatile unsigned int *)(KVA +0x40000060)) + +#define GPU_IRQ (1 << 8) +#define CNTPNS_IRQ (1 << 1) +void sync_handler_currentEL_ELx(); +void sync_handler_lowerEL_64(uint64_t sp_addr); +void irq_handler_currentEL_ELx(); +void irq_handler_lowerEL_64(); +void default_handler(); +void enable_interrupt(); +void disable_interrupt(); \ No newline at end of file diff --git a/lab6/kernel/include/gpio.h b/lab6/kernel/include/gpio.h new file mode 100644 index 000000000..b8a73e84d --- /dev/null +++ b/lab6/kernel/include/gpio.h @@ -0,0 +1,22 @@ +#pragma once +#include "mmu.h" + +#define MMIO_BASE (KVA + 0x3F000000) +#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000)) +#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004)) +#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008)) +#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C)) +#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010)) +#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014)) +#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C)) +#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020)) +#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028)) +#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034)) +#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038)) +#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040)) +#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044)) +#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064)) +#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068)) +#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094)) +#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098)) +#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C)) diff --git a/lab6/kernel/include/math.h b/lab6/kernel/include/math.h new file mode 100644 index 000000000..b3c6a317f --- /dev/null +++ b/lab6/kernel/include/math.h @@ -0,0 +1,6 @@ +#ifndef MATH_H +#define MATH_H + +int pow(int base, int exponent); + +#endif \ No newline at end of file diff --git a/lab6/kernel/include/mbox.h b/lab6/kernel/include/mbox.h new file mode 100644 index 000000000..1de89d020 --- /dev/null +++ b/lab6/kernel/include/mbox.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/* a properly aligned buffer */ +extern unsigned int mbox[8]; + +#define MBOX_REQUEST 0 + +/* channels */ +#define MBOX_CH_POWER 0 +#define MBOX_CH_FB 1 +#define MBOX_CH_VUART 2 +#define MBOX_CH_VCHIQ 3 +#define MBOX_CH_LEDS 4 +#define MBOX_CH_BTNS 5 +#define MBOX_CH_TOUCH 6 +#define MBOX_CH_COUNT 7 +#define MBOX_CH_PROP 8 + +/* tags */ +#define MBOX_TAG_SETPOWER 0x28001 +#define MBOX_TAG_SETCLKRATE 0x38002 +#define MBOX_TAG_GETSERIAL 0x10004 +#define MBOX_TAG_GETBDVS 0x00010002 +#define MBOX_TAG_GETARMMEM 0x00010005 + +#define MBOX_TAG_LAST 0 + +int mbox_call(unsigned char ch, unsigned int* mbox); diff --git a/lab6/kernel/include/mmu.h b/lab6/kernel/include/mmu.h new file mode 100644 index 000000000..98751e80b --- /dev/null +++ b/lab6/kernel/include/mmu.h @@ -0,0 +1,51 @@ +#pragma once + +#define KVA 0xffff000000000000 +#define PERIPHERAL_BASE 0x3f000000 + +#define TCR_CONFIG_REGION_48bit (((64 - 48) << 0) | ((64 - 48) << 16)) +#define TCR_CONFIG_4KB ((0b00 << 14) | (0b10 << 30)) +#define TCR_CONFIG_DEFAULT (TCR_CONFIG_REGION_48bit | TCR_CONFIG_4KB) + +#define MAIR_DEVICE_nGnRnE 0b00000000 +#define MAIR_NORMAL_NOCACHE 0b01000100 +#define MAIR_IDX_DEVICE_nGnRnE 0 +#define MAIR_IDX_NORMAL_NOCACHE 1 + +#define PAGE_TABLE_BASE 0x30000000 +#define PGD_BASE (PAGE_TABLE_BASE + 0x0000) +#define PUD_BASE (PAGE_TABLE_BASE + 0x1000) +#define PMD_BASE (PAGE_TABLE_BASE + 0x2000) +#define PTE_BASE (PAGE_TABLE_BASE + 0x4000) + +#define PD_TABLE 0b11 +#define PD_BLOCK 0b01 +#define PD_PAGE 0b11 +#define PD_ACCESS (1 << 10) +#define PD_USER_RW (0b01 << 6) +#define PD_USER_R (0b11 << 6) +#define PD_UXN (1L << 54) +#define PD_PXN (1L << 53) + +#define BOOT_PGD_ATTR (PD_TABLE) +#define BOOT_PUD_ATTR (PD_TABLE) +#define BOOT_PMD_ATTR (PD_TABLE) +#define BOOT_PTE_DEVICE_nGnRnE_ATTR \ + (PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_PAGE) +#define BOOT_PTE_NORMAL_NOCACHE_ATTR \ + (PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_PAGE) + +#include +#include "thread.h" + +#define VA2PA(addr) ((uint64_t)(addr) & (uint64_t)0x0000ffffffffffff) +#define PA2VA(addr) ((uint64_t)(addr) | (uint64_t)0xffff000000000000) + +#define PERIPHERAL_START 0x3c000000 +#define PERIPHERAL_END 0x3f000000 + +void init_page_table(thread_info *thread, uint64_t **table); +void update_page_table(thread_info *thread, uint64_t virtual_addr, + uint64_t physical_addr, uint64_t permission); +uint64_t el0_VA2PA(thread_info *thread, uint64_t virtual_addr); + \ No newline at end of file diff --git a/lab6/kernel/include/mmu_value.h b/lab6/kernel/include/mmu_value.h new file mode 100644 index 000000000..d959a96a4 --- /dev/null +++ b/lab6/kernel/include/mmu_value.h @@ -0,0 +1,30 @@ +#pragma once +#define KVA 0xffff000000000000 +#define PERIPHERAL_BASE 0x3f000000 + +#define TCR_CONFIG_REGION_48bit (((64 - 48) << 0) | ((64 - 48) << 16)) +#define TCR_CONFIG_4KB ((0b00 << 14) | (0b10 << 30)) +#define TCR_CONFIG_DEFAULT (TCR_CONFIG_REGION_48bit | TCR_CONFIG_4KB) + +#define MAIR_DEVICE_nGnRnE 0b00000000 +#define MAIR_NORMAL_NOCACHE 0b01000100 +#define MAIR_IDX_DEVICE_nGnRnE 0 +#define MAIR_IDX_NORMAL_NOCACHE 1 + +#define PAGE_TABLE_BASE 0x30000000 +#define PGD_BASE (PAGE_TABLE_BASE + 0x0000) +#define PUD_BASE (PAGE_TABLE_BASE + 0x1000) +#define PMD_BASE (PAGE_TABLE_BASE + 0x2000) +#define PTE_BASE (PAGE_TABLE_BASE + 0x4000) + +#define PD_TABLE 0b11 +#define PD_BLOCK 0b01 +#define PD_PAGE 0b11 +#define PD_ACCESS (1 << 10) +#define BOOT_PGD_ATTR (PD_TABLE) +#define BOOT_PUD_ATTR (PD_TABLE) +#define BOOT_PMD_ATTR (PD_TABLE) +#define BOOT_PTE_DEVICE_nGnRnE_ATTR \ + (PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_PAGE) +#define BOOT_PTE_NORMAL_NOCACHE_ATTR \ + (PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_PAGE) diff --git a/lab6/kernel/include/power.h b/lab6/kernel/include/power.h new file mode 100644 index 000000000..4216fa556 --- /dev/null +++ b/lab6/kernel/include/power.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +void power_off(); +void reset(); diff --git a/lab6/kernel/include/printf.h b/lab6/kernel/include/printf.h new file mode 100644 index 000000000..e58f666dc --- /dev/null +++ b/lab6/kernel/include/printf.h @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. +// Use this instead of bloated standard/newlib printf. +// These routines are thread safe and reentrant. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _PRINTF_H_ +#define _PRINTF_H_ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Output a character to a custom device like UART, used by the printf() function + * This function is declared here only. You have to write your custom implementation somewhere + * \param character Character to output + */ +void _putchar(char character); + + +/** + * Tiny printf implementation + * You have to implement _putchar if you use printf() + * To avoid conflicts with the regular printf() API it is overridden by macro defines + * and internal underscore-appended functions like printf_() are used + * \param format A string that specifies the format of the output + * \return The number of characters that are written into the array, not counting the terminating null character + */ +#define printf printf_ +int printf_(const char* format, ...); + + +/** + * Tiny sprintf implementation + * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD! + * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output! + * \param format A string that specifies the format of the output + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define sprintf sprintf_ +int sprintf_(char* buffer, const char* format, ...); + + +/** + * Tiny snprintf/vsnprintf implementation + * \param buffer A pointer to the buffer where to store the formatted string + * \param count The maximum number of characters to store in the buffer, including a terminating null character + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that COULD have been written into the buffer, not counting the terminating + * null character. A value equal or larger than count indicates truncation. Only when the returned value + * is non-negative and less than count, the string has been completely written. + */ +#define snprintf snprintf_ +#define vsnprintf vsnprintf_ +int snprintf_(char* buffer, size_t count, const char* format, ...); +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); + + +/** + * Tiny vprintf implementation + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define vprintf vprintf_ +int vprintf_(const char* format, va_list va); + + +/** + * printf with output function + * You may use this as dynamic alternative to printf() with its fixed _putchar() output + * \param out An output function which takes one character and an argument pointer + * \param arg An argument pointer for user data passed to output function + * \param format A string that specifies the format of the output + * \return The number of characters that are sent to the output function, not counting the terminating null character + */ +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); + + +#ifdef __cplusplus +} +#endif + + +#endif // _PRINTF_H_ \ No newline at end of file diff --git a/lab6/kernel/include/shell.h b/lab6/kernel/include/shell.h new file mode 100644 index 000000000..5659d7a97 --- /dev/null +++ b/lab6/kernel/include/shell.h @@ -0,0 +1,30 @@ +#include "uart.h" +#include "string.h" +#include "power.h" +#include "mbox.h" +#include "cpio.h" +#include "timer.h" +#include "exception.h" +#include "alloc.h" +#include "utils.h" +#include "thread.h" +#include "printf.h" + +void clean_buffer(char * buffer, int buffer_len); +void command_help(); +void command_hello(); +void command_not_found(char * buffer); +void command_ls(); +void command_cat(char* pathname); +void command_mailbox(); +void command_test(); +void command_load_user_program(const char *program_name); +void command_set_timeout(char *args); +void command_buddy_test(); +void command_dma_test(); +void command_thread_test1() ; +void command_thread_test2() ; +void command_thread_test3() ; +void command_thread_test4() ; +void parse_command(char * buffer); +void run_shell(); diff --git a/lab6/kernel/include/string.h b/lab6/kernel/include/string.h new file mode 100644 index 000000000..5782c937d --- /dev/null +++ b/lab6/kernel/include/string.h @@ -0,0 +1,6 @@ +#pragma once + +int strcmp(const char *p1, const char *p2); +int strncmp(const char *s1, const char *s2, unsigned n); +int strlen(const char *s); +char *strstr(const char *s, const char *find); \ No newline at end of file diff --git a/lab6/kernel/include/thread.h b/lab6/kernel/include/thread.h new file mode 100644 index 000000000..95a33907c --- /dev/null +++ b/lab6/kernel/include/thread.h @@ -0,0 +1,83 @@ +#pragma once + +#include "utils.h" + +#define STACK_SIZE 4096 +#define USER_STACK_BASE ((uint64_t)0xffffffffb000) +#define USER_PROGRAM_BASE 0x80000 +#define USER_PROGRAM_SIZE (512 * kb) + +#define MAX_PAGE_FRAME_PER_THREAD 1000 + +#define THREAD_DEAD 1 +#define THREAD_FORK 2 +#define THREAD_READY 4 + +typedef struct { + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t fp; + uint64_t lr; + uint64_t sp; +} cpu_context; + +typedef struct thread_info { + cpu_context context; + uint32_t pid; + uint32_t child_pid; + int status; + uint64_t trap_frame_addr; + uint64_t kernel_stack_base; + uint64_t user_stack_base; + uint64_t user_program_base; + uint32_t user_program_size; + uint64_t *pgd; + uint32_t page_frame_ids[MAX_PAGE_FRAME_PER_THREAD]; + uint32_t page_frame_count; + struct thread_info *next; +} thread_info; + +typedef struct { + thread_info *head, *tail; +} thread_queue; + +typedef struct { + uint64_t x[31]; +} trap_frame_t; + +thread_queue run_queue; +uint32_t thread_cnt; + +extern thread_info *get_current(); +extern void switch_to(thread_info *, thread_info *); + +void foo(); +void thread_test1(); +void thread_test2(); +void thread_test3(); +void thread_test4(); + +void thread_init(); +thread_info *thread_create(void (*func)()); +void schedule(); +void idle(); +void exit(); +void run_queue_push(thread_info *thread); +void kill_zombies(); +void exec(const char *program_name, const char **argv); +void fork(uint64_t sp); +void handle_fork(); +void create_child(thread_info *parent, thread_info *child); +void kill (int kill_pid); + +uint64_t thread_allocate_page(thread_info *thread, uint64_t size); +void thread_free_page(thread_info *thread); +void switch_pgd(uint64_t next_pgd); \ No newline at end of file diff --git a/lab6/kernel/include/timer.h b/lab6/kernel/include/timer.h new file mode 100644 index 000000000..c0edbd6b9 --- /dev/null +++ b/lab6/kernel/include/timer.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include "mmu.h" +#define CORE0_TIMER_IRQ_CTRL ((volatile unsigned int *)(KVA + 0x40000040)) + +typedef struct timeout_event { + uint32_t register_time; + uint32_t duration; + void (*callback)(char *); + char args[20]; + struct timeout_event *prev, *next; +} timeout_event; + +timeout_event *timeout_queue_head, *timeout_queue_tail; + +void timeout_event_init(); +void core_timer_enable(); +void core_timer_disable(); +void core_timer_handler_lowerEL_64(); +void core_timer_handler_currentEL_ELx(); +void add_timer(void (*callback)(char *), char *args, uint32_t duration); +uint64_t get_current_time(); +void set_expired_time(uint32_t duration); +void timer_callback(char *msg); \ No newline at end of file diff --git a/lab6/kernel/include/uart.h b/lab6/kernel/include/uart.h new file mode 100644 index 000000000..e624348c0 --- /dev/null +++ b/lab6/kernel/include/uart.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#pragma once +#include "gpio.h" +#include +#define ARM_IRQ_REG_BASE (MMIO_BASE + 0x0000b000) + +#define IRQ_PENDING_1 ((volatile unsigned int *)(ARM_IRQ_REG_BASE + 0x00000204)) +#define ENABLE_IRQS_1 ((volatile unsigned int *)(ARM_IRQ_REG_BASE + 0x00000210)) +#define DISABLE_IRQS_1 \ + ((volatile unsigned int *)(ARM_IRQ_REG_BASE + 0x0000021c)) + +#define AUX_IRQ (1 << 29) + +#define UART_BUFFER_SIZE 20 +char read_buf[UART_BUFFER_SIZE]; +char write_buf[UART_BUFFER_SIZE]; +int read_buf_start, read_buf_end; +int write_buf_start, write_buf_end; + +void uart_init(); +void uart_send(unsigned int c); +char uart_getc(); +uint32_t uart_gets(char *buf, uint32_t size); +void uart_puts(char *s); +void uart_hex(unsigned int d); +void uart_putc(char c); +void uart_int(int x); +uint32_t uart_write(char *s, uint32_t size); + +void enable_uart_interrupt(); +void disable_uart_interrupt(); +void assert_transmit_interrupt(); +void clear_transmit_interrupt(); +void uart_handler(); +char uart_async_getc(); +void uart_async_puts(char *str); \ No newline at end of file diff --git a/lab6/kernel/include/utils.h b/lab6/kernel/include/utils.h new file mode 100644 index 000000000..085a90b13 --- /dev/null +++ b/lab6/kernel/include/utils.h @@ -0,0 +1,15 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ +#include +uint64_t hex_to_int64(char* num); +uint8_t hex_to_int8(char hex); +uint64_t hex2int(char *hex, int len); +uint64_t align_up(uint64_t addr, uint64_t alignment); +uint64_t align_up_exp(uint64_t n); +#define kb ((uint64_t)0x400) +#define mb ((uint64_t)0x100000) +#define gb ((uint64_t)0x40000000) +uint64_t log2(uint64_t num); +void delay(int num); +uint32_t be2le(uint32_t x); +#endif diff --git a/lab6/kernel/src/alloc.c b/lab6/kernel/src/alloc.c new file mode 100644 index 000000000..a4d026a16 --- /dev/null +++ b/lab6/kernel/src/alloc.c @@ -0,0 +1,446 @@ +#include "alloc.h" +#include "uart.h" +#include "utils.h" +#include "printf.h" + +void buddy_test() { + print_frame_lists(); + uint64_t size[6] = { + PAGE_SIZE * 1, PAGE_SIZE * 13, PAGE_SIZE * 16, + PAGE_SIZE * 2, PAGE_SIZE * 4, PAGE_SIZE * 8, + }; + page_frame *frame_ptr[6]; + printf("********** buddy allocation test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + frame_ptr[i] = buddy_allocate(size[i]); + printf("Successfully allocate %lld pages\n", size[i] / PAGE_SIZE); + // if (c == 'p') + print_frame_lists(); + } + print_frame_lists(); + printf("********** buddy free test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + buddy_free(frame_ptr[i]); + printf("Successfully free %lld pages\n", size[i] / PAGE_SIZE); + // if (c == 'p') + print_frame_lists(); + } +} + +void dma_test() { + print_frame_lists(); + print_dma_list(); + // int *ptr1 = malloc(sizeof(int)); + // int *ptr2 = malloc(sizeof(int) * 1024); + // int *ptr3 = malloc(sizeof(int)); + // print_dma_list(); + // free(ptr1); + // print_dma_list(); + // free(ptr2); + // print_dma_list(); + // free(ptr3); + + uint64_t size[6] = { + sizeof(int) * 1, sizeof(int) * 8, sizeof(int) * 2201, + sizeof(int) * 9, sizeof(int) * 3068, sizeof(int) * 100, + }; + void *ptr[6]; + + printf("********** malloc test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + ptr[i] = malloc(size[i]); + printf("Successfully allocate %lld bytes in address %p\n", size[i], ptr[i]); + // if (c == 'p') { + print_frame_lists(); + print_dma_list(); // printf( + // "put frame index %d back to free lists (4K x 2^%lld = %lld KB)\n", + // id, frames[id].order, 1 << (frames[id].order + 2)); + // } + } + // print_frame_lists(); + // print_dma_list(); + printf("********** free test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + free(ptr[i]); + printf("Successfully free %lld bytes in address %p\n", size[i], ptr[i]); + // if (c == 'p') { + print_frame_lists(); + print_dma_list(); + // } + } +} + +void buddy_init() { + for (int i = 0; i < MAX_PAGE_NUM; i++) { + frames[i].id = i; + frames[i].order = -1; + frames[i].is_allocated = 0; + frames[i].addr = PAGE_BASE_ADDR + i * PAGE_SIZE; + frames[i].next = 0; + } + for (int i = 0; i < FRAME_LIST_NUM; i++) { + free_frame_lists[i] = 0; + used_frame_lists[i] = 0; + } + frames[0].order = MAX_FRAME_ORDER; + free_frame_lists[MAX_FRAME_ORDER] = &frames[0]; + free_dma_list = 0; +} + +page_frame * buddy_allocate(uint64_t size) { + // printf("Enter size (kb): "); + // int kb_size = read_i(); + uint64_t page_num = size / PAGE_SIZE; + if (size % PAGE_SIZE != 0) page_num++; + page_num = align_up_exp(page_num); + uint64_t order = log2(page_num); + + for (uint64_t i = order; i <= MAX_FRAME_ORDER; i++) { + // printf("i = "); + // uart_int(i); + // printf("\n"); + + if (free_frame_lists[i]) { + int cur_id = free_frame_lists[i]->id; + free_frame_lists[i] = free_frame_lists[i]->next; + frames[cur_id].order = order; + frames[cur_id].is_allocated = 1; + frames[cur_id].next = used_frame_lists[order]; + used_frame_lists[order] = &frames[cur_id]; + // printf("allocate frame index %d (4K x 2^%lld = %lld KB)\n", cur_id, order, + // 1 << (order + 2)); + + // release redundant memory block + for (; i > order; i--) { + int id = cur_id + (1 << (i - 1)); + frames[id].order = i - 1; + frames[id].is_allocated = 0; + frames[id].next = free_frame_lists[i - 1]; + free_frame_lists[i - 1] = &frames[id]; + // printf( + // "put frame index %d back to free lists (4K x 2^%lld = %lld KB)\n", + // id, frames[id].order, 1 << (frames[id].order + 2)); + } + // printf("\n"); + // print_frame_lists(); + return &frames[cur_id]; + } + } + return 0; +} + +void buddy_free(page_frame *frame) { + // printf("Enter address (hex): "); + // uint64_t addr = read_h(); + uint64_t index = frame->id; + if (!frames[index].is_allocated) { + printf("Error: it is already free\n"); + return; + } + uint64_t order = frames[index].order; + // printf("index :"); + // uart_int(index); + // printf("order :"); + // uart_int(order); + // printf("\n"); + buddy_unlink(index, 1); + // iterative merge + while (order <= MAX_FRAME_ORDER) { + uint64_t target_index = index ^ (1 << order); // XOR to find same size page + // printf("target_index :"); + // uart_int(target_index); + // printf("\n"); + if ((target_index >= MAX_PAGE_NUM) || frames[target_index].is_allocated || + (frames[target_index].order != order)) + break; + + // printf("merge with frame index %d (4K x 2^%lld = %lld KB)\n", target_index, + // frames[target_index].order, 1 << (frames[target_index].order + 2)); + order += 1; + // iterative part + if (index > target_index) index = target_index; + } + frames[index].order = order; + frames[index].next = free_frame_lists[order]; + free_frame_lists[order] = &frames[index]; + // printf("put frame index %d back (4K x 2^%lld = %lld KB)\n", index, + // frames[index].order, 1 << (frames[index].order + 2)); + // print_frame_lists(); +} + +void buddy_unlink(int index, int type) { + uint64_t order = frames[index].order; + frames[index].order = -1; + frames[index].is_allocated = 0; + + if (type == 0) { + if (free_frame_lists[order] == &frames[index]) { + free_frame_lists[order] = frames[index].next; + frames[index].next = 0; + } else { + // printf("=========linked list search free=======\n"); + for (page_frame *cur = free_frame_lists[order]; cur; cur = cur->next) { + if (cur->next == &frames[index]) { + cur->next = frames[index].next; + frames[index].next = 0; + break; + } + } + } + } + if (type == 1) { + if (used_frame_lists[order] == &frames[index]) { + used_frame_lists[order] = frames[index].next; + frames[index].next = 0; + } else { + // printf("=========linked list search used=======\n"); + for (page_frame *cur = used_frame_lists[order]; cur; cur = cur->next) { + if (cur->next == &frames[index]) { + cur->next = frames[index].next; + frames[index].next = 0; + break; + } + } + } + } +} + +void print_frame_lists() { + printf("========================\n"); + printf("Free frame lists: \n"); + for (int i = MAX_FRAME_ORDER; i >= 0; i--) { + printf("4K x 2^%d (%d KB):", i, 1 << (i + 2)); + for (page_frame *cur = free_frame_lists[i]; cur; cur = cur->next) { + printf(" index %d(0x%x)", cur->id, cur->addr); + } + printf("\n"); + } + printf("\n"); + printf("Used frame lists: \n"); + for (int i = MAX_FRAME_ORDER; i >= 0; i--) { + printf("4K x 2^%d (%d KB):", i, 1 << (i + 2)); + for (page_frame *cur = used_frame_lists[i]; cur; cur = cur->next) { + printf(" index %d(0x%x)", cur->id, cur->addr); + } + printf("\n"); + } + printf("========================\n"); +} + +void *malloc(uint64_t size) { + dma_header *free_slot = 0; + uint64_t min_size = ((uint64_t)1) << 63; + // printf("min_size :"); + // uart_int(min_size); + // printf("\n"); + // printf("size :"); + // uart_int(size); + // printf("\n"); + // find the smallest free slot which is bigger than the required size + for (dma_header *cur = free_dma_list; cur; cur = cur->next) { + // printf("find the smallest free slot which is bigger than the required size\n"); + + uint64_t data_size = cur->total_size - align_up(sizeof(dma_header), 8); + if (data_size >= align_up(size, 8) && data_size < min_size) { + free_slot = cur; + min_size = data_size; + } + } + + uint64_t allocated_size = align_up(sizeof(dma_header), 8) + align_up(size, 8); + // printf("allocated_size :"); + // uart_int(allocated_size); + // printf("\n"); + if (free_slot) { + // printf("have free_slot\n"); + + uint64_t addr = (uint64_t)free_slot; + uint64_t total_size = free_slot->total_size; + // rewrite the found free slot + free_slot->total_size = allocated_size; + free_slot->used_size = size; + free_slot->is_allocated = 1; + if (free_slot->prev) { + // printf("if (free_slot->prev)\n"); + free_slot->prev->next = free_slot->next; + } + if (free_slot->next) { + // printf("if (free_slot->next)\n"); + free_slot->next->prev = free_slot->prev; + } + if (free_dma_list == free_slot){ + // printf("if (free_slot->prev)\n"); + free_dma_list = free_slot->next; + } + free_slot->prev = 0; + free_slot->next = 0; + + // create another free slot if remaining size is big enough + int64_t free_size = + total_size - allocated_size - align_up(sizeof(dma_header), 8); + if (free_size > 0) { + dma_header *new_header = (dma_header *)(addr + allocated_size); + new_header->total_size = total_size - allocated_size; + new_header->used_size = 0; + new_header->is_allocated = 0; + new_header->frame_ptr = free_slot->frame_ptr; + new_header->prev = 0; + new_header->next = free_dma_list; + if (free_dma_list) free_dma_list->prev = new_header; + free_dma_list = new_header; + } else { + free_slot->total_size = total_size; + } + return (void *)(addr + align_up(sizeof(dma_header), 8)); + } else { + // printf("no free_slot\n"); + + // allocate a page + page_frame *frame_ptr = buddy_allocate(allocated_size); + uint64_t addr = frame_ptr->addr; + // printf("addr :"); + // uart_hex(addr); + // printf("\n"); + // create a free slot + dma_header *allocated_header = (dma_header *)addr; + allocated_header->total_size = allocated_size; + allocated_header->used_size = size; + allocated_header->is_allocated = 1; + allocated_header->frame_ptr = frame_ptr; + allocated_header->prev = 0; + allocated_header->next = 0; + // create another free slot if remaining size is big enough + uint64_t order = frame_ptr->order; + uint64_t total_size = (1 << order) * 4 * kb; + int64_t free_size = total_size - allocated_size - align_up(sizeof(dma_header), 8); + // printf("order :"); + // uart_int(order); + // printf("\n"); + // printf("total_size :"); + // uart_int(total_size); + // printf("\n"); + // printf("free_size :"); + // uart_int(free_size); + // printf("\n"); + if (free_size > 0) { + dma_header *new_header = (dma_header *)(addr + allocated_size); + new_header->total_size = total_size - allocated_size; + new_header->used_size = 0; + new_header->is_allocated = 0; + new_header->frame_ptr = frame_ptr; + new_header->prev = 0; + new_header->next = free_dma_list; + if (free_dma_list) free_dma_list->prev = new_header; + free_dma_list = new_header; + } else { + allocated_header->total_size = total_size; + } + return (void *)(addr + align_up(sizeof(dma_header), 8)); + } + return 0; +} + +void free(void *ptr) { + uint64_t target_addr = (uint64_t)ptr - align_up(sizeof(dma_header), 8); + dma_header *target_header = (dma_header *)target_addr; + target_header->used_size = 0; + target_header->is_allocated = 0; + target_header->prev = 0; + target_header->next = free_dma_list; + if (free_dma_list) free_dma_list->prev = target_header; + free_dma_list = target_header; + + // uart_hex((uint64_t)ptr); + // printf("\n"); + // uart_hex(target_addr); + // printf("\n"); + + page_frame *frame_ptr = target_header->frame_ptr; + uint64_t base_addr = frame_ptr->addr; + uint64_t order = frame_ptr->order; + uint64_t total_frame_size = (1 << order) * 4 * kb; + uint64_t boundary = base_addr + total_frame_size; + + // uart_hex(base_addr); + // printf("\n"); + // uart_hex(total_size); + // printf("\n"); + + // merge next slot if it is free + uint64_t next_addr = target_addr + target_header->total_size; + dma_header *next_header = (dma_header *)next_addr; + if (next_addr < boundary && !next_header->is_allocated) { + if (next_header->prev) next_header->prev->next = next_header->next; + if (next_header->next) next_header->next->prev = next_header->prev; + if (free_dma_list == next_header) free_dma_list = next_header->next; + next_header->prev = 0; + next_header->next = 0; + target_header->total_size += next_header->total_size; + } + // uart_int(target_header->total_size); + // printf("\n"); + // print_dma_list(); + + // merge previous slot if it is free + uint64_t current_addr = base_addr; + while (current_addr < boundary) { + dma_header *header = (dma_header *)current_addr; + uint64_t next_addr = current_addr + header->total_size; + // uart_hex(current_addr); + // printf("\n"); + // uart_hex(next_addr); + // printf("\n"); + if (next_addr == target_addr) { + if (!header->is_allocated) { + header->total_size += target_header->total_size; + // uart_int(header->total_size); + // printf("\n"); + if (target_header->prev) + target_header->prev->next = target_header->next; + if (target_header->next) + target_header->next->prev = target_header->prev; + if (free_dma_list == target_header) free_dma_list = target_header->next; + target_header->prev = 0; + target_header->next = 0; + } + break; + } + current_addr = next_addr; + } + + // free page frame if all slots are free + dma_header *base_header = (dma_header *)base_addr; + if (base_header->total_size == total_frame_size) { + if (base_header->prev) base_header->prev->next = base_header->next; + if (base_header->next) base_header->next->prev = base_header->prev; + if (free_dma_list == base_header) free_dma_list = base_header->next; + base_header->prev = 0; + base_header->next = 0; + buddy_free(frame_ptr); + } +} + +void print_dma_list() { + printf("========================\n"); + printf("Free DMA slots: \n"); + for (dma_header *cur = free_dma_list; cur; cur = cur->next) { + printf("size: "); + uart_int(cur->total_size - align_up(sizeof(dma_header), 8)); + printf(", frame index: "); + uart_int(cur->frame_ptr->id); + printf("\n"); + } + printf("========================\n"); +} diff --git a/lab6/kernel/src/cpio.c b/lab6/kernel/src/cpio.c new file mode 100644 index 000000000..bf8716491 --- /dev/null +++ b/lab6/kernel/src/cpio.c @@ -0,0 +1,85 @@ +#include "cpio.h" +#include "printf.h" +#include "string.h" +#include "utils.h" +void cpio_ls() { + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + printf("%s ", pathname); + + ptr = align_up(ptr + namesize, 4); + ptr = align_up(ptr + filesize, 4); + } + printf("\n"); +} + +void cpio_cat(char *pathname_to_cat) { + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + + ptr = align_up(ptr + namesize, 4); + if (strcmp(pathname, pathname_to_cat) == 0) { + char *content = (char *)ptr; + for (unsigned long long i = 0; i < filesize; i++) { + printf("%c", content[i]); + } + printf("\n"); + return; + } + ptr = align_up(ptr + filesize, 4); + } + printf("No such file\n"); +} + +uint32_t cpio_load_user_program(const char *target_program, + uint64_t target_addr) { + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + + ptr = align_up(ptr + namesize, 4); + if (strcmp(pathname, target_program) == 0) { + char *content = (char *)ptr; + char *target_content = (char *)target_addr; + for (unsigned long long i = 0; i < filesize; i++) { + target_content[i] = content[i]; + } + return filesize; + } + ptr = align_up(ptr + filesize, 4); + } + printf("No such file\n"); + return 0; +} \ No newline at end of file diff --git a/lab6/kernel/src/delays.c b/lab6/kernel/src/delays.c new file mode 100644 index 000000000..aba77264d --- /dev/null +++ b/lab6/kernel/src/delays.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" + +#define SYSTMR_LO ((volatile unsigned int*)(MMIO_BASE+0x00003004)) +#define SYSTMR_HI ((volatile unsigned int*)(MMIO_BASE+0x00003008)) + +/** + * Wait N CPU cycles (ARM CPU only) + */ +void wait_cycles(unsigned int n) +{ + if(n) while(n--) { asm volatile("nop"); } +} + +/** + * Wait N microsec (ARM CPU only) + */ +void wait_msec(unsigned int n) +{ + register unsigned long f, t, r; + // get the current counter frequency + asm volatile ("mrs %0, cntfrq_el0" : "=r"(f)); + // read the current counter + asm volatile ("mrs %0, cntpct_el0" : "=r"(t)); + // calculate expire value for counter + t+=((f/1000)*n)/1000; + do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(roff_dt_struct); + uint64_t strings_addr = dtb_addr + be2le(header->off_dt_strings); + + if (all) { + dtb_parse(struct_addr, strings_addr, default_probe); + } else { + printf("\ndevice for mailbox driver function: \n"); + dtb_parse(struct_addr, strings_addr, mailbox_probe); + printf("\ndevice for gpio driver function: \n"); + dtb_parse(struct_addr, strings_addr, gpio_probe); + printf("\ndevice for rtx3080ti driver function: \n"); + dtb_parse(struct_addr, strings_addr, rtx3080ti_probe); + } +} + +void dtb_parse(uint64_t struct_addr, uint64_t strings_addr, + void (*callback)(uint64_t, uint64_t, int)) { + int depth = 0; + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + callback(struct_addr, strings_addr, depth); + struct_addr = ignore_current_node(struct_addr, strings_addr); + depth++; + } else if (token == FDT_END_NODE) { + depth--; + } else if (token == FDT_NOP) { + continue; + } else if (token == FDT_END) { + break; + } + } +} + +uint64_t ignore_current_node(uint64_t struct_addr, uint64_t strings_addr) { + char *name = (char *)(struct_addr); + struct_addr += strlen(name) + 1; + struct_addr = align_up(struct_addr, 4); + + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_END_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_PROP) { + uint32_t len = dtb_read_int(struct_addr); + len = be2le(len); + struct_addr += 4; + uint32_t nameoff = dtb_read_int(struct_addr); + nameoff = be2le(nameoff); + struct_addr += 4; + struct_addr += len; + struct_addr = align_up(struct_addr, 4); + } else if (token == FDT_NOP) { + continue; + } + } + return struct_addr; +} + +uint64_t print_node(uint64_t struct_addr, uint64_t strings_addr, int depth) { + char *name = (char *)(struct_addr); + struct_addr += strlen(name) + 1; + struct_addr = align_up(struct_addr, 4); + for (int i = 0; i < depth; i++) printf(" "); + printf("node: %s\n", name); + + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + break; + } else if (token == FDT_END_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_PROP) { + struct_addr = print_property(struct_addr, strings_addr, depth + 1); + } else if (token == FDT_NOP) { + continue; + } + } + return struct_addr; +} + +uint64_t print_property(uint64_t struct_addr, uint64_t strings_addr, + int depth) { + uint32_t len = dtb_read_int(struct_addr); + len = be2le(len); + struct_addr += 4; + uint32_t nameoff = dtb_read_int(struct_addr); + nameoff = be2le(nameoff); + struct_addr += 4; + char *property = (char *)(strings_addr + nameoff); + + int value_type = 0; + char *is_u32[] = {"phandle", "#address-cells", "#size-cells", "virtual-reg", + "interrupt-parent"}; + char *is_string[] = {"compatible", "model", "status", "name", "device_type"}; + + for (int i = 0; i < sizeof(is_u32) / sizeof(is_u32[0]); i++) { + if (strcmp(property, is_u32[i]) == 0) { + value_type = 1; + break; + } + } + for (int i = 0; i < sizeof(is_string) / sizeof(is_string[0]); i++) { + if (strcmp(property, is_string[i]) == 0) { + value_type = 2; + break; + } + } + + for (int i = 0; i < depth; i++) printf(" "); + printf("%s = ", property); + + // hex, e.g. <0x4600 0x100> + if (value_type == 0) { + int count = 0; + printf("<"); + for (uint32_t i = 0; i < len; i += 4) { + if (count > 0) printf(" "); + count++; + uint32_t num = dtb_read_int(struct_addr); + num = be2le(num); + struct_addr += 4; + printf("0x%x", num); + } + printf(">"); + } + // int, e.g. <1> + if (value_type == 1) { + uint32_t num = dtb_read_int(struct_addr); + num = be2le(num); + struct_addr += 4; + printf("<%d>", num); + } + // string or string list, e.g. "fsl,MPC8349EMITX" or "fsl,mpc8641", "ns16550" + if (value_type == 2) { + int count = 0; + uint64_t end = struct_addr + len; + + while (struct_addr < end) { + if (count > 0) printf(", "); + count++; + char *string = (char *)struct_addr; + struct_addr += strlen(string) + 1; + printf("\"%s\"", string); + } + } + printf("\n"); + + struct_addr = align_up(struct_addr, 4); + return struct_addr; +} + +uint32_t dtb_read_int(uint64_t addr_ptr) { + char *base = (char *)(addr_ptr); + uint32_t value = 0; + for (int i = 3; i >= 0; i--) { + value = (value << 8) | (*(base + i) & 0xFF); + } + return value; +} + +// char *dtb_read_string(uint64_t addr_ptr) { +// char *base = (char *)(addr_ptr); +// char *string_start = base; +// return string_start; +// } \ No newline at end of file diff --git a/lab6/kernel/src/exception.S b/lab6/kernel/src/exception.S new file mode 100644 index 000000000..9ef00764b --- /dev/null +++ b/lab6/kernel/src/exception.S @@ -0,0 +1,127 @@ +// save general registers to stack +.macro save_reg + sub sp, sp, 32 * 9 + stp x0, x1, [sp, 16 * 0] + stp x2, x3, [sp, 16 * 1] + stp x4, x5, [sp, 16 * 2] + stp x6, x7, [sp, 16 * 3] + stp x8, x9, [sp, 16 * 4] + stp x10, x11, [sp, 16 * 5] + stp x12, x13, [sp, 16 * 6] + stp x14, x15, [sp, 16 * 7] + stp x16, x17, [sp, 16 * 8] + stp x18, x19, [sp, 16 * 9] + stp x20, x21, [sp, 16 * 10] + stp x22, x23, [sp, 16 * 11] + stp x24, x25, [sp, 16 * 12] + stp x26, x27, [sp, 16 * 13] + stp x28, x29, [sp, 16 * 14] + //str x30, [sp, 16 * 15] + mrs x10, spsr_el1 + mrs x11, elr_el1 + mrs x12, sp_el0 + stp x30, x10, [sp, 16 * 15] + stp x11, x12, [sp, 16 * 16] +.endm + +// load general registers from stack +.macro load_reg + ldp x30, x10, [sp, 16 * 15] + ldp x11, x12, [sp, 16 * 16] + msr spsr_el1, x10 + msr elr_el1, x11 + msr sp_el0, x12 + ldp x0, x1, [sp, 16 * 0] + ldp x2, x3, [sp, 16 * 1] + ldp x4, x5, [sp, 16 * 2] + ldp x6, x7, [sp, 16 * 3] + ldp x8, x9, [sp, 16 * 4] + ldp x10, x11, [sp, 16 * 5] + ldp x12, x13, [sp, 16 * 6] + ldp x14, x15, [sp, 16 * 7] + ldp x16, x17, [sp, 16 * 8] + ldp x18, x19, [sp, 16 * 9] + ldp x20, x21, [sp, 16 * 10] + ldp x22, x23, [sp, 16 * 11] + ldp x24, x25, [sp, 16 * 12] + ldp x26, x27, [sp, 16 * 13] + ldp x28, x29, [sp, 16 * 14] + //ldr x30, [sp, 16 * 15] + //ldp x30, x10, [sp, 16 * 15] + //ldp x11, x12, [sp, 16 * 16] + //msr spsr_el1, x10 + //msr elr_el1, x11 + //msr sp_el0, x12 + add sp, sp, 32 * 9 +.endm + +.align 11 // vector table should be aligned to 0x800 +.global exception_vector_table +exception_vector_table: + b _default_handler // branch to a handler function. + .align 7 // entry size is 0x80, .align will pad 0 + b _default_handler + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + + b _sync_handler_currentEL_ELx + .align 7 + b _irq_handler_currentEL_ELx + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + + b _sync_handler_lowerEL_64 + .align 7 + b _irq_handler_lowerEL_64 + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + + b _default_handler + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + +_sync_handler_currentEL_ELx: + save_reg + bl sync_handler_currentEL_ELx // exception.c + load_reg + eret + +_sync_handler_lowerEL_64: + save_reg + //mrs x0, sp_el0 + mov x0, sp + bl sync_handler_lowerEL_64 // exception.c + load_reg + eret + +_irq_handler_currentEL_ELx: + save_reg + bl irq_handler_currentEL_ELx // exception.c + load_reg + eret + +_irq_handler_lowerEL_64: + save_reg + bl irq_handler_lowerEL_64 // exception.c + load_reg + eret + +_default_handler: + save_reg + bl default_handler // exception.c + load_reg + eret \ No newline at end of file diff --git a/lab6/kernel/src/exception.c b/lab6/kernel/src/exception.c new file mode 100644 index 000000000..b5ebc3bca --- /dev/null +++ b/lab6/kernel/src/exception.c @@ -0,0 +1,119 @@ +#include "exception.h" +#include "uart.h" +#include "utils.h" +#include "timer.h" +#include "string.h" +#include "thread.h" +#include "printf.h" +#include "mbox.h" +int count = 0; + +void enable_interrupt() { asm volatile("msr DAIFClr, 0xf"); } + +void disable_interrupt() { asm volatile("msr DAIFSet, 0xf"); } + +void sync_handler_currentEL_ELx() { + printf("[sync_handler_currentEL_ELx]\n"); + + uint64_t spsr_el1, elr_el1, esr_el1; + asm volatile("mrs %0, spsr_el1" : "=r"(spsr_el1)); + asm volatile("mrs %0, elr_el1" : "=r"(elr_el1)); + asm volatile("mrs %0, esr_el1" : "=r"(esr_el1)); + uint32_t ec = (esr_el1 >> 26) & 0x3f; + printf("EC: %x\n", ec); + while(1){;} + // printf("SPSR_EL1: 0x%08x\n", spsr_el1); + // printf("ELR_EL1: 0x%08x\n", elr_el1); + // printf("ESR_EL1: 0x%08x\n", esr_el1); + // printf("hi\n"); +} + +void sync_handler_lowerEL_64(uint64_t sp) { + // printf("sync_handler_lowerEL_64 sp : %x\n",sp); + uint64_t spsr_el1, elr_el1, esr_el1; + asm volatile("mrs %0, spsr_el1" : "=r"(spsr_el1)); + asm volatile("mrs %0, elr_el1" : "=r"(elr_el1)); + asm volatile("mrs %0, esr_el1" : "=r"(esr_el1)); + // printf("sync, SPSR_EL1: 0x%08x\n", spsr_el1); + // printf("ELR_EL1: 0x%08x\n", elr_el1); + // printf("ESR_EL1: 0x%08x\n", esr_el1); + + uint32_t ec = (esr_el1 >> 26) & 0x3f; + // printf("EC: %x\n", ec); + + if (ec == 0b010101) { // SVC instruction + uint64_t iss; + asm volatile("mov %0, x8" : "=r"(iss)); + // printf("syscall number: %d\n", iss); + trap_frame_t *trap_frame = (trap_frame_t *)sp; + + if (iss == 0) { // getpid + uint32_t pid = get_current()->pid; + trap_frame->x[0] = pid; + } else if (iss == 1) { // uartread + disable_uart_interrupt(); + enable_interrupt(); + char *str = (char *)(trap_frame->x[0]); + uint32_t size = (uint32_t)(trap_frame->x[1]); + size = uart_gets(str, size); + trap_frame->x[0] = size; + } else if (iss == 2) { // uartwrite + char *str = (char *)(trap_frame->x[0]); + trap_frame->x[0] = uart_write(str,trap_frame->x[1]); + } else if (iss == 3) { // exec + const char *program_name = (const char *)trap_frame->x[0]; + const char **argv = (const char **)trap_frame->x[1]; + exec(program_name, argv); + } else if (iss == 4) { // fork + fork(sp); + // User shell need excute after child mbox_call in qemu + // But in real machine can work without below code + if(get_current()->pid==1){ + int magic_sleep = 50000000; + while(magic_sleep--){} + } + } else if (iss == 5) { // exit + exit(); + } else if (iss == 6) { // mbox_call + thread_info *cur = get_current(); + unsigned int * mbox_user_va = (unsigned int *)trap_frame->x[1]; + unsigned int * mbox_user_pa = (unsigned int *)el0_VA2PA(cur,(uint64_t)mbox_user_va); + unsigned int * mbox_kernel_va = (unsigned int *) PA2VA(mbox_user_pa); + trap_frame->x[0] = mbox_call(trap_frame->x[0],mbox_kernel_va); + } else if (iss == 7) { // kill + kill((int)trap_frame->x[0]); + } + } +} + +void irq_handler_currentEL_ELx() { + // printf("====irq_handler_currentEL_ELx=====\n"); + + disable_interrupt(); + uint32_t is_uart = (*IRQ_PENDING_1 & AUX_IRQ); + uint32_t is_core_timer = (*CORE0_IRQ_SOURCE & 0x2); + + if (is_uart) { + uart_handler(); + } else if (is_core_timer) { + core_timer_handler_lowerEL_64(); + } + enable_interrupt(); +} + +void irq_handler_lowerEL_64() { + // printf("====irq_handler_lowerEL_64=====\n"); + disable_interrupt(); + uint32_t is_uart = (*IRQ_PENDING_1 & AUX_IRQ); + uint32_t is_core_timer = (*CORE0_IRQ_SOURCE & 0x2); + + if (is_uart) { + uart_handler(); + } else if (is_core_timer) { + core_timer_handler_lowerEL_64(); + } + enable_interrupt(); +} + + +void default_handler() { uart_puts("===== default handler =====\n"); } diff --git a/lab6/kernel/src/linker.ld b/lab6/kernel/src/linker.ld new file mode 100644 index 000000000..f956ce931 --- /dev/null +++ b/lab6/kernel/src/linker.ld @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +SECTIONS +{ + . = 0xffff000000000000; + . += 0x80000; + .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) } + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) } + PROVIDE(_data = .); + .data : { *(.data .data.* .gnu.linkonce.d*) } + .bss (NOLOAD) : { + . = ALIGN(16); + __bss_start = .; + *(.bss .bss.*) + *(COMMON) + __bss_end = .; + } + _end = .; + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} +__bss_size = (__bss_end - __bss_start)>>3; \ No newline at end of file diff --git a/lab6/kernel/src/main.c b/lab6/kernel/src/main.c new file mode 100644 index 000000000..869bc35f7 --- /dev/null +++ b/lab6/kernel/src/main.c @@ -0,0 +1,29 @@ +#include "uart.h" +#include "string.h" +#include "power.h" +#include "mbox.h" +#include "cpio.h" +#include "timer.h" +#include "exception.h" +#include "alloc.h" +#include "utils.h" +#include "thread.h" +#include "printf.h" +#include "shell.h" + +// #include "device_tree.h" +void main() +{ + // set up serial console + uart_init(); + buddy_init(); + //welcome message + uart_puts("*****************************\r\n"); + uart_puts("* welcome OSC2022 *\r\n"); + uart_puts("*****************************\r\n"); + timeout_event_init(); + enable_interrupt(); + thread_init(); + run_shell(); +} + diff --git a/lab6/kernel/src/math.c b/lab6/kernel/src/math.c new file mode 100644 index 000000000..2b89b515c --- /dev/null +++ b/lab6/kernel/src/math.c @@ -0,0 +1,9 @@ +int pow(int base, int exponent) +{ + int result = 1; + for ( ; exponent > 0; exponent--) + { + result = result * base; + } + return result; +} \ No newline at end of file diff --git a/lab6/kernel/src/mbox.c b/lab6/kernel/src/mbox.c new file mode 100644 index 000000000..2ff36adf5 --- /dev/null +++ b/lab6/kernel/src/mbox.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" +#include "mmu.h" +#include "printf.h" +#include "mbox.h" +/* mailbox message buffer */ +unsigned int __attribute__((aligned(16))) mbox[8]; + +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) +#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) +#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) +#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) +#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) +#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) +#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) +#define MBOX_RESPONSE 0x80000000 +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 + +/** + * Make a mailbox call. Returns 0 on failure, non-zero on success + */ +int mbox_call(unsigned char ch, unsigned int *user_mbox) +{ + unsigned int r = (((unsigned int)((unsigned long)VA2PA(user_mbox))&~0xF) | (ch&0xF)); + /* wait until we can write to the mailbox */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_FULL); + /* write the address of our message to the mailbox with channel identifier */ + *MBOX_WRITE = r; + /* now wait for the response */ + while(1) { + /* is there a response? */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY); + /* is it a response to our message? */ + if(r == *MBOX_READ) + /* is it a valid successful response? */ + // printf("[2]user_mbox[1]=%p\n",user_mbox[1]); + // printf("[2]user_mbox[28]=%p\n",user_mbox[28]); + + return user_mbox[1]==MBOX_RESPONSE; + } + return 0; +} diff --git a/lab6/kernel/src/mmu.c b/lab6/kernel/src/mmu.c new file mode 100644 index 000000000..9832de2d5 --- /dev/null +++ b/lab6/kernel/src/mmu.c @@ -0,0 +1,80 @@ +#include "mmu.h" + +#include +#include "alloc.h" +#include "printf.h" +#include "thread.h" +#include "exception.h" +#include "mbox.h" + +void init_page_table(thread_info *thread, uint64_t **table) { + *table = (uint64_t *)thread_allocate_page(thread, PAGE_SIZE); + for (int i = 0; i < 512; i++) { + *((*table) + i) = 0; + } + // printf("[init] next table virtual addr: 0x%llx\n", (uint64_t)(*table)); + *table = (uint64_t *)VA2PA(*table); +} + +void update_page_table(thread_info *thread, uint64_t virtual_addr, + uint64_t physical_addr, uint64_t flags) { + if (thread->pgd == 0) { + printf("Invalid PGD!!\n"); + return; + } + + uint32_t index[4] = { + (virtual_addr >> 39) & 0x1ff, (virtual_addr >> 30) & 0x1ff, + (virtual_addr >> 21) & 0x1ff, (virtual_addr >> 12) & 0x1ff}; + + // printf("virtual addr: 0x%llx", virtual_addr); + // printf(", index: 0x%llx", index[0]); + // printf(", index: 0x%llx", index[1]); + // printf(", index: 0x%llx", index[2]); + // printf(", index: 0x%llx\n", index[3]); + // printf("physical addr: 0x%llx\n", physical_addr); + + uint64_t *table = (uint64_t *)PA2VA(thread->pgd); + // printf("table: 0x%llx\n", (uint64_t)table); + for (int level = 0; level < 3; level++) { + if (table[index[level]] == 0) { + // printf("level: %d, index: 0x%llx ", level, index[level]); + init_page_table(thread, (uint64_t **)&(table[index[level]])); + table[index[level]] |= PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_TABLE; + } + // printf("table PA: 0x%llx\n", (uint64_t)table[index[level]]); + table = (uint64_t *)PA2VA(table[index[level]] & ~0xfff); + // printf("table VA: 0x%llx\n", (uint64_t)table); + } + table[index[3]] = + physical_addr | BOOT_PTE_NORMAL_NOCACHE_ATTR | flags; + // printf("page PA: 0x%llx\n", (uint64_t)table[index[3]]); +} + +uint64_t el0_VA2PA(thread_info *thread, uint64_t virtual_addr) { + disable_interrupt(); + uint32_t index[4] = { + (virtual_addr >> 39) & 0x1ff, (virtual_addr >> 30) & 0x1ff, + (virtual_addr >> 21) & 0x1ff, (virtual_addr >> 12) & 0x1ff}; + uint32_t offset = virtual_addr &0xfff; + // printf("offset =%p\n",offset); + printf("[el0_VA2PA]virtual addr: %p\n", virtual_addr); + // printf(", index: 0x%llx", index[0]); + // printf(", index: 0x%llx", index[1]); + // printf(", index: 0x%llx", index[2]); + // printf(", index: 0x%llx\n", index[3]); + + uint64_t *table = (uint64_t *)PA2VA(thread->pgd); + // printf("pgd: %p\n", (uint64_t)table); + for (int level = 0; level < 3; level++) { + if (table[index[level]] == 0) { + printf("[el0_VA2PA]*Your page table implement unsuccessful*\n"); + break; + } + // printf(" [el0_VA2PA]table PA: 0x%p\n", (uint64_t)table[index[level]]); + table = (uint64_t *)PA2VA(table[index[level]] & ~0xfff); + // printf("table VA: 0x%llx\n", (uint64_t)table); + } + printf("[el0_VA2PA]transfer to physical addr: %p\n",(table[index[3]]& ~0xfff)|offset); + return (table[index[3]]& ~0xfff)|offset; +} \ No newline at end of file diff --git a/lab6/kernel/src/power.c b/lab6/kernel/src/power.c new file mode 100644 index 000000000..c066b6259 --- /dev/null +++ b/lab6/kernel/src/power.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" +#include "mbox.h" +#include "delays.h" + +#define PM_RSTC ((volatile unsigned int*)(MMIO_BASE+0x0010001c)) +#define PM_RSTS ((volatile unsigned int*)(MMIO_BASE+0x00100020)) +#define PM_WDOG ((volatile unsigned int*)(MMIO_BASE+0x00100024)) +#define PM_WDOG_MAGIC 0x5a000000 +#define PM_RSTC_FULLRST 0x00000020 + +/** + * Shutdown the board + */ +void power_off() +{ + unsigned long r; + + // power off devices one by one + for(r=0;r<16;r++) { + mbox[0]=8*4; + mbox[1]=MBOX_REQUEST; + mbox[2]=MBOX_TAG_SETPOWER; // set power state + mbox[3]=8; + mbox[4]=8; + mbox[5]=(unsigned int)r; // device id + mbox[6]=0; // bit 0: off, bit 1: no wait + mbox[7]=MBOX_TAG_LAST; + mbox_call(MBOX_CH_PROP,mbox); + } + + // power off gpio pins (but not VCC pins) + *GPFSEL0 = 0; *GPFSEL1 = 0; *GPFSEL2 = 0; *GPFSEL3 = 0; *GPFSEL4 = 0; *GPFSEL5 = 0; + *GPPUD = 0; + wait_cycles(150); + *GPPUDCLK0 = 0xffffffff; *GPPUDCLK1 = 0xffffffff; + wait_cycles(150); + *GPPUDCLK0 = 0; *GPPUDCLK1 = 0; // flush GPIO setup + + // power off the SoC (GPU + CPU) + r = *PM_RSTS; r &= ~0xfffffaaa; + r |= 0x555; // partition 63 used to indicate halt + *PM_RSTS = PM_WDOG_MAGIC | r; + *PM_WDOG = PM_WDOG_MAGIC | 10; + *PM_RSTC = PM_WDOG_MAGIC | PM_RSTC_FULLRST; +} + +/** + * Reboot + */ +void reset() +{ + unsigned int r; + // trigger a restart by instructing the GPU to boot from partition 0 + r = *PM_RSTS; r &= ~0xfffffaaa; + *PM_RSTS = PM_WDOG_MAGIC | r; // boot from partition 0 + *PM_WDOG = PM_WDOG_MAGIC | 10; + *PM_RSTC = PM_WDOG_MAGIC | PM_RSTC_FULLRST; +} diff --git a/lab6/kernel/src/printf.c b/lab6/kernel/src/printf.c new file mode 100644 index 000000000..13b92a7b4 --- /dev/null +++ b/lab6/kernel/src/printf.c @@ -0,0 +1,921 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. These routines are thread +// safe and reentrant! +// Use this instead of the bloated standard/newlib printf cause these use +// malloc for printf (and may not be thread safe). +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "printf.h" + + +// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the +// printf_config.h header file +// default: undefined +#ifdef PRINTF_INCLUDE_CONFIG_H +#include "printf_config.h" +#endif + + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +// support for the floating point type (%f) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +// support for exponential floating point notation (%e/%g) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL +#define PRINTF_SUPPORT_EXPONENTIAL +#endif + +// define the default floating point precision +// default: 6 digits +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +// define the largest float suitable to print with %f +// default: 1e9 +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +// support for the long long types (%llu or %p) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +// support for the ptrdiff_t type (%t) +// ptrdiff_t is normally defined in as long or long long type +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + + +// import float.h for DBL_MAX +#if defined(PRINTF_SUPPORT_FLOAT) +#include +#endif + +// my custom implementation of _putchar +#include "uart.h" +void _putchar(char character) { + if (character == '\n') uart_send('\r'); + uart_send(character); +} + + +// output function type +typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); + + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void* arg); + void* arg; +} out_fct_wrap_type; + + +// internal buffer output +static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) +{ + if (idx < maxlen) { + ((char*)buffer)[idx] = character; + } +} + + +// internal null output +static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)character; (void)buffer; (void)idx; (void)maxlen; +} + + +// internal _putchar wrapper +static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)buffer; (void)idx; (void)maxlen; + if (character) { + _putchar(character); + } +} + + +// internal output function wrapper +static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)idx; (void)maxlen; + if (character) { + // buffer is the output fct pointer + ((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg); + } +} + + +// internal secure strlen +// \return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int _strnlen_s(const char* str, size_t maxsize) +{ + const char* s; + for (s = str; *s && maxsize--; ++s); + return (unsigned int)(s - str); +} + + +// internal test if char is a digit (0-9) +// \return true if char is a digit +static inline bool _is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + + +// internal ASCII string to unsigned int conversion +static unsigned int _atoi(const char** str) +{ + unsigned int i = 0U; + while (_is_digit(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + + +// output the specified string in reverse, taking care of any zero-padding +static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) +{ + const size_t start_idx = idx; + + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + + +// internal itoa format +static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) +{ + // pad leading zeros + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + // handle hash + if (flags & FLAGS_HASH) { + if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { + len--; + if (len && (base == 16U)) { + len--; + } + } + if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } + else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } + else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_NTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +// internal itoa for 'long' type +static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} + + +// internal itoa for 'long long' type +#if defined(PRINTF_SUPPORT_LONG_LONG) +static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#endif // PRINTF_SUPPORT_LONG_LONG + + +#if defined(PRINTF_SUPPORT_FLOAT) + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags); +#endif + + +// internal ftoa for fixed decimal floating point +static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + + // powers of 10 + static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + + // test for special values + if (value != value) + return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + // test for very large values + // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad + if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); +#else + return 0U; +#endif + } + + // test for negative + bool negative = false; + if (value < 0) { + negative = true; + value = 0 - value; + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + // limit precision to 9, cause a prec >= 10 can lead to overflow errors + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { + buf[len++] = '0'; + prec--; + } + + int whole = (int)value; + double tmp = (value - whole) * pow10[prec]; + unsigned long frac = (unsigned long)tmp; + diff = tmp - frac; + + if (diff > 0.5) { + ++frac; + // handle rollover, e.g. case 0.99 with prec 1 is 1.0 + if (frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } + else if (diff < 0.5) { + } + else if ((frac == 0U) || (frac & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++frac; + } + + if (prec == 0U) { + diff = value - (double)whole; + if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++whole; + } + } + else { + unsigned int count = prec; + // now do fractional part, as an unsigned number + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(48U + (frac % 10U)); + if (!(frac /= 10U)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + // add decimal + buf[len++] = '.'; + } + } + + // do whole part, number is reversed + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(48 + (whole % 10)); + if (!(whole /= 10)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + // check for NaN and special values + if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { + return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); + } + + // determine the sign + const bool negative = value < 0; + if (negative) { + value = -value; + } + + // default precision + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // determine the decimal exponent + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + union { + uint64_t U; + double F; + } conv; + + conv.F = value; + int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 + conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) + // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 + int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^expval but we want to be sure it won't overflow + exp2 = (int)(expval * 3.321928094887362 + 0.5); + const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = (uint64_t)(exp2 + 1023) << 52U; + // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if (value < conv.F) { + expval--; + conv.F /= 10; + } + + // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters + unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; + + // in "%g" mode, "prec" is the number of *significant figures* not decimals + if (flags & FLAGS_ADAPT_EXP) { + // do we want to fall-back to "%f" mode? + if ((value >= 1e-4) && (value < 1e6)) { + if ((int)prec > expval) { + prec = (unsigned)((int)prec - expval - 1); + } + else { + prec = 0; + } + flags |= FLAGS_PRECISION; // make sure _ftoa respects precision + // no characters in exponent + minwidth = 0U; + expval = 0; + } + else { + // we use one sigfig for the whole part + if ((prec > 0) && (flags & FLAGS_PRECISION)) { + --prec; + } + } + } + + // will everything fit? + unsigned int fwidth = width; + if (width > minwidth) { + // we didn't fall-back so subtract the characters required for the exponent + fwidth -= minwidth; + } else { + // not enough characters, so go back to default sizing + fwidth = 0U; + } + if ((flags & FLAGS_LEFT) && minwidth) { + // if we're padding on the right, DON'T pad the floating part + fwidth = 0U; + } + + // rescale the float value + if (expval) { + value /= conv.F; + } + + // output the floating part + const size_t start_idx = idx; + idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); + + // output the exponent part + if (minwidth) { + // output the exponential symbol + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + // output the exponent value + idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS); + // might need to right-pad spaces + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + + +// internal vsnprintf +static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) +{ + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + // use null output function + out = _out_null; + } + + while (*format) + { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } + else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break; + case '-': flags |= FLAGS_LEFT; format++; n = 1U; break; + case '+': flags |= FLAGS_PLUS; format++; n = 1U; break; + case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break; + case '#': flags |= FLAGS_HASH; format++; n = 1U; break; + default : n = 0U; break; + } + } while (n); + + // evaluate width field + width = 0U; + if (_is_digit(*format)) { + width = _atoi(&format); + } + else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } + else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (_is_digit(*format)) { + precision = _atoi(&format); + } + else if (*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l' : + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h' : + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't' : + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j' : + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z' : + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default : + break; + } + + // evaluate specifier + switch (*format) { + case 'd' : + case 'i' : + case 'u' : + case 'x' : + case 'X' : + case 'o' : + case 'b' : { + // set the base + unsigned int base; + if (*format == 'x' || *format == 'X') { + base = 16U; + } + else if (*format == 'o') { + base = 8U; + } + else if (*format == 'b') { + base = 2U; + } + else { + base = 10U; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + } + else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags); + } + else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); + idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f' : + case 'F' : + if (*format == 'F') flags |= FLAGS_UPPERCASE; + idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + case 'c' : { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's' : { + const char* p = va_arg(va, char*); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p' : { + width = sizeof(void*) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + const bool is_ll = sizeof(uintptr_t) == sizeof(long long); + if (is_ll) { + idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags); + } + else { +#endif + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%' : + out('%', buffer, idx++, maxlen); + format++; + break; + + default : + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + + +/////////////////////////////////////////////////////////////////////////////// + +int printf_(const char* format, ...) +{ + va_list va; + va_start(va, format); + char buffer[1]; + const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + +int sprintf_(char* buffer, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + +int snprintf_(char* buffer, size_t count, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); + va_end(va); + return ret; +} + + +int vprintf_(const char* format, va_list va) +{ + char buffer[1]; + return _vsnprintf(_out_char, buffer, (size_t)-1, format, va); +} + + +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va) +{ + return _vsnprintf(_out_buffer, buffer, count, format, va); +} + + +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) +{ + va_list va; + va_start(va, format); + const out_fct_wrap_type out_fct_wrap = { out, arg }; + const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va); + va_end(va); + return ret; +} \ No newline at end of file diff --git a/lab6/kernel/src/shell.c b/lab6/kernel/src/shell.c new file mode 100644 index 000000000..0da635426 --- /dev/null +++ b/lab6/kernel/src/shell.c @@ -0,0 +1,259 @@ +#include "uart.h" +#include "string.h" +#include "power.h" +#include "mbox.h" +#include "cpio.h" +#include "timer.h" +#include "exception.h" +#include "alloc.h" +#include "utils.h" +#include "thread.h" +#include "printf.h" +#include "dtb.h" + +void clean_buffer(char * buffer, int buffer_len) +{ + for(int i = 0 ; i < buffer_len ; i++) + buffer[i] = '\0'; +} + +void command_help() +{ + uart_puts("This is kernel shell\n"); + uart_puts("help\t\t: print this help menu\n"); + uart_puts("hello\t\t: print Hello World!\n"); + uart_puts("reboot\t\t: reboot the device\n"); + uart_puts("mailbox\t\t: show information through mailbox\n"); + uart_puts("dtb\t\t: parse device tree message\n"); + uart_puts("dtb all\t\t: parse device tree message\n"); + uart_puts("ls\t\t: show all files\n"); + uart_puts("cat\t\t: show file info\n"); + uart_puts("test\t\t: test simple allocator\n"); + uart_puts("user\t\t: load and run a user program in the initramfs\n"); + uart_puts("timer\t\t: core_timer_enable\n"); + uart_puts("puts\t\t: async_puts Test Message\n"); + uart_puts("buddy test\t: test for buddy system\n"); + uart_puts("dma test \t: test for dynamic memory allocation\n"); + uart_puts("setTimeout [MESSAGE] [SECONDS]\t: prints MESSAGE after SECONDS\n"); +} + +void command_hello() +{ + uart_puts("\n"); + uart_puts("Hello World!\n"); +} + +void command_not_found(char * buffer) +{ + uart_puts("\n"); + uart_puts("command *"); + uart_puts(buffer); + uart_puts("* not exist\n"); +} + +void command_ls(){ + cpio_ls(); +} + + +void command_cat(char* pathname){ + cpio_cat(pathname); +} + +void command_mailbox() +{ + // get serail number + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETSERIAL; // get serial number command + mbox[3] = 8; // buffer size + mbox[4] = 8; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + uart_puts("\n"); + if (mbox_call(MBOX_CH_PROP,mbox)) { + uart_puts("serial number is: "); + uart_hex(mbox[6]); + uart_hex(mbox[5]); + uart_puts("\n"); + } + // get board revision + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETBDVS; // get board revision + mbox[3] = 4; // buffer size + mbox[4] = 4; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + if (mbox_call(MBOX_CH_PROP,mbox)) { + uart_puts("board revision is: "); + uart_hex(mbox[6]); + uart_hex(mbox[5]); + uart_puts("\n"); + } + + // get arm memory + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETARMMEM; // get arm memory info + mbox[3] = 8; // buffer size + mbox[4] = 8; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + if (mbox_call(MBOX_CH_PROP,mbox)) { + uart_puts("arm base addr: "); + uart_hex(mbox[5]); + uart_puts("\n"); + uart_puts("arm addr size: "); + uart_hex(mbox[6]); + uart_puts("\n"); + } +} + +unsigned int get_board_revision() +{ + // get board revision + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETBDVS; // get board revision + mbox[3] = 4; // buffer size + mbox[4] = 4; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + if (mbox_call(MBOX_CH_PROP,mbox)) { + uart_puts("board revision is: "); + uart_hex(mbox[6]); + uart_hex(mbox[5]); + uart_puts("\n"); + } + return mbox[5]; +} + +void command_test() +{ + // test malloc + uart_puts("\r"); + uart_puts("test malloc\n"); + char * c = malloc(30); + c[0]='a'; + c[1]='b'; + c[2]='\0'; + uart_puts("c:"); + uart_puts(c); + uart_puts("\r\n"); + char * d = malloc(30); + d[0]='x'; + d[1]='y'; + d[2]='\0'; + uart_puts("d:"); + uart_puts(d); + uart_puts("\r\n"); +} + +void command_load_user_program(const char *program_name) { + uint64_t spsr_el1 = 0x0; // EL0t with interrupt enabled + uint64_t target_addr = 0x30100000; + uint64_t target_sp = 0x10007030; + cpio_load_user_program(program_name, target_addr); + // core_timer_enable(); + asm volatile("msr spsr_el1, %0" : : "r"(spsr_el1)); + asm volatile("msr elr_el1, %0" : : "r"(target_addr)); + asm volatile("msr sp_el0, %0" : : "r"(target_sp)); + asm volatile("eret"); +} + +void command_set_timeout(char *args) { + uint32_t duration = 0; + for (int i = 0; args[i]; i++) { + if (args[i] == ' ') { + for (int j = i + 1; args[j]; j++) { + duration = duration * 10 + (args[j] - '0'); + } + args[i] = '\0'; + break; + } + } + add_timer(timer_callback, args, duration); +} + +void command_buddy_test() { + buddy_test(); +} +void command_dma_test() { + dma_test(); +} +void command_thread_test1() { + thread_test1(); +} +void command_thread_test2() { + thread_test2(); +} +void command_thread_test3() { + thread_test3(); +} +void command_thread_test4() { + thread_test4(); +} +void command_dtb_print(int all) { dtb_print(all); } + +void parse_command(char * buffer) +{ + if ( !strcmp(buffer, "help")) command_help(); + else if ( !strcmp(buffer, "hello")) command_hello(); + else if ( !strcmp(buffer, "mailbox")) command_mailbox(); + else if ( !strcmp(buffer, "ls")) command_ls(); + else if ( !strncmp(buffer, "cat", 3)) command_cat(&buffer[4]); + else if ( !strcmp(buffer, "test")) command_test(); + else if ( !strcmp(buffer, "reboot")) reset(); + else if ( !strncmp(buffer, "run", 3)) command_load_user_program(&buffer[4]); + else if ( !strcmp(buffer, "puts")) uart_async_puts("Test Message!\n"); + else if ( !strcmp(buffer, "timer")) core_timer_enable(); + else if ( !strncmp(buffer, "setTimeout", 10)) command_set_timeout(&buffer[11]); + else if ( !strcmp(buffer, "buddy test")) command_buddy_test(); + else if ( !strcmp(buffer, "dma test")) command_dma_test(); + else if ( !strcmp(buffer, "dtb")) command_dtb_print(0); + else if ( !strcmp(buffer, "dtb all")) command_dtb_print(1); + else if ( !strcmp(buffer, "t1")) command_thread_test1(); + else if ( !strcmp(buffer, "t2")) command_thread_test2(); + else if ( !strcmp(buffer, "t3")) command_thread_test3(); + else if ( !strcmp(buffer, "t4")) command_thread_test4(); + else command_not_found(buffer); +} + +void run_shell() +{ + char buffer[64]={'\0'}; + int buffer_len=0; + //clean buffer + clean_buffer(buffer, 64); + // echo everything back + while(1) { + printf("# "); + while(1){ + char c = uart_async_getc(); + if(c=='\n')uart_send('\r'); + uart_send(c); + if(c=='\n'){ + //parse buffer + parse_command(buffer); + //clean buffer + clean_buffer(buffer, 64); + buffer_len = 0; + break; + } + buffer[buffer_len++] = c; + } + } +} diff --git a/lab6/kernel/src/start.S b/lab6/kernel/src/start.S new file mode 100644 index 000000000..8ef3894c7 --- /dev/null +++ b/lab6/kernel/src/start.S @@ -0,0 +1,131 @@ +#include "mmu_value.h" +.section ".text.boot" + +.global _start + +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #3 + cbz x1, master + b hang_loop // cpu id > 0, stop + +master: // cpu id == 0 + + // save dtb loading address + ldr x1, =0x9000000 + str x0, [x1] + bl from_el2_to_el1 + bl set_exception_vector_table + +set_virtual_memory: + ldr x0, =TCR_CONFIG_DEFAULT + msr tcr_el1, x0 + + ldr x0, =( \ + (MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | \ + (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8)) \ + ) + msr mair_el1, x0 + ldr x0, =PGD_BASE // PGD's page frame at 0x0 + ldr x1, =PUD_BASE // PGD's page frame at 0x0 + ldr x2, =PMD_BASE // PGD's page frame at 0x0 + ldr x3, =PTE_BASE // PGD's page frame at 0x0 + + ldr x4, =BOOT_PGD_ATTR + mov x5, x1 + orr x6, x5, x4 // combine the physical address of next level page with attribute. + str x6, [x0] + + ldr x4, =BOOT_PUD_ATTR + mov x5, x2 + orr x6, x5, x4 + str x6, [x1] // 1st 1GB mapped by the 1st entry of PUD + add x5, x5, #0x1000 + orr x6, x5, x4 + str x6, [x1, 8] // 2nd 1GB mapped by the 2nd entry of PUD + + ldr x4, =BOOT_PMD_ATTR + mov x5, x3 + mov x7, x2 + mov x9, #(512 * 2) + +set_PMD: + orr x6, x5, x4 + str x6, [x7] // 2MB block + sub x9, x9, #1 + add x7, x7, #8 + add x5, x5, #0x1000 + cbnz x9, set_PMD + + ldr x4, =BOOT_PTE_NORMAL_NOCACHE_ATTR + mov x5, #0x00000000 + mov x7, x3 + mov x9, #(512 * 512 * 2) + ldr x10, =PERIPHERAL_BASE + +set_PTE: + cmp x5, x10 + blt normal_mem + ldr x4, =BOOT_PTE_DEVICE_nGnRnE_ATTR + +normal_mem: + orr x6, x5, x4 + str x6, [x7] // 4KB page + sub x9, x9, #1 + add x7, x7, #8 + add x5, x5, #(1 << 12) + cbnz x9, set_PTE + + msr ttbr0_el1, x0 // load PGD to the bottom translation based register. + msr ttbr1_el1, x0 // also load PGD to the upper translation based register. + + mrs x2, sctlr_el1 + orr x2 , x2, 1 + msr sctlr_el1, x2 // enable MMU, cache remains disabled + + ldr x2, =boot_rest // indirect branch to the virtual address + br x2 + +boot_rest: + // clear bss + ldr x1, =__bss_start + ldr w2, =__bss_size + +clear_bss_start: + cbz w2, clear_bss_done + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, clear_bss_start + + +clear_bss_done: + // set top of stack just before our code (stack grows to a lower address per AAPCS64) + ldr x1, =_start + mov sp, x1 + + bl main // jump to C code, should not return + b hang_loop // for failsafe, halt this core too + +from_el2_to_el1: + mov x0, (1 << 31) // EL1 uses aarch64 + msr hcr_el2, x0 + mov x0, 0x3c5 // EL1h with interrupt disabled + msr spsr_el2, x0 + msr elr_el2, lr + + // IMPORTANT: disable exceptions of accessing the SIMD and floating-point registers + mov x0, #(3 << 20) + msr cpacr_el1, x0 + + eret // return to EL1 + +set_exception_vector_table: + // adr x0, exception_vector_table + ldr x0, =exception_vector_table + msr vbar_el1, x0 + ret + +hang_loop: + wfe + b hang_loop \ No newline at end of file diff --git a/lab6/kernel/src/string.c b/lab6/kernel/src/string.c new file mode 100644 index 000000000..00a00ebfd --- /dev/null +++ b/lab6/kernel/src/string.c @@ -0,0 +1,76 @@ +#include "string.h" + +/* Compare S1 and S2, returning less than, equal to or + greater than zero if S1 is lexicographically less than, + equal to or greater than S2. */ +int strcmp(const char *p1, const char *p2) { + const unsigned char *s1 = (const unsigned char *)p1; + const unsigned char *s2 = (const unsigned char *)p2; + unsigned char c1, c2; + do { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0') return c1 - c2; + } while (c1 == c2); + return c1 - c2; +} + +/* Compare no more than N characters of S1 and S2, + returning less than, equal to or greater than zero + if S1 is lexicographically less than, equal to or + greater than S2. */ +int strncmp(const char *s1, const char *s2, unsigned n) { + unsigned char c1 = '\0'; + unsigned char c2 = '\0'; + if (n >= 4) { + unsigned n4 = n >> 2; + do { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + } while (--n4 > 0); + n &= 3; + } + while (n > 0) { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + n--; + } + return c1 - c2; +} + +int strlen(const char *s) { + int len = 0; + while (s[len] != '\0') { + len++; + } + return len; +} + +/* + * Find the first occurrence of find in s. + */ +char *strstr(const char *s, const char *find) { + char c, sc; + int len; + if ((c = *find++) != 0) { + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) return 0; + } while (sc != c); + } while (strncmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} \ No newline at end of file diff --git a/lab6/kernel/src/thread.S b/lab6/kernel/src/thread.S new file mode 100644 index 000000000..514958efa --- /dev/null +++ b/lab6/kernel/src/thread.S @@ -0,0 +1,26 @@ +.global switch_to +switch_to: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + + ldp x19, x20, [x1, 16 * 0] + ldp x21, x22, [x1, 16 * 1] + ldp x23, x24, [x1, 16 * 2] + ldp x25, x26, [x1, 16 * 3] + ldp x27, x28, [x1, 16 * 4] + ldp fp, lr, [x1, 16 * 5] + ldr x9, [x1, 16 * 6] + mov sp, x9 + msr tpidr_el1, x1 + ret + +.global get_current +get_current: + mrs x0, tpidr_el1 + ret \ No newline at end of file diff --git a/lab6/kernel/src/thread.c b/lab6/kernel/src/thread.c new file mode 100644 index 000000000..162b5a66b --- /dev/null +++ b/lab6/kernel/src/thread.c @@ -0,0 +1,369 @@ +#include "thread.h" +#include "timer.h" +#include "alloc.h" +#include "cpio.h" +#include "exception.h" +#include "printf.h" +#include "utils.h" +#include "shell.h" + +void foo() { + for (int i = 0; i < 4; ++i) { + printf("Thread id: %d, %d\r\n", get_current()->pid, i); + delay(1000000); + schedule(); + } + exit(); + return; +} + +void user_test1() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("mailbox_test", argv); +} + +void user_test2() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("my_test2", argv); +} +void user_test3() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("fork_test", argv); +} + +void user_test4() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("syscall.img", argv); +} + +void user_test5() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("vm.img", argv); +} + +void thread_test1() { // mailbox test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test1); + idle(); +} + +void thread_test2() { // fork test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test3); + idle(); +} + +void thread_test3() { //vedio player1 test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test4); + idle(); +} + +void thread_test4() { //vedio player1 test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test5); + idle(); +} + +void thread_init() { + run_queue.head = 0; + run_queue.tail = 0; + thread_cnt = 0; +} + +thread_info *thread_create(void (*func)()) { + // printf("create thread pid = %d\n",thread_cnt); + thread_info *thread = (thread_info *)malloc(sizeof(thread_info)); + + uint64_t *pgd; + asm volatile("mrs %0, ttbr1_el1" : "=r"(pgd)); + thread->pgd = pgd; + for (int i = 0; i < MAX_PAGE_FRAME_PER_THREAD; i++) + thread->page_frame_ids[i] = 0; + thread->page_frame_count = 0; + + thread->pid = thread_cnt++; + thread->status = THREAD_READY; + thread->next = 0; + thread->kernel_stack_base = thread_allocate_page(thread, STACK_SIZE); + thread->user_stack_base = 0; + thread->user_program_base = 0; + thread->context.fp = thread->kernel_stack_base + STACK_SIZE; + thread->context.lr = (uint64_t)func; + thread->context.sp = thread->kernel_stack_base + STACK_SIZE; + run_queue_push(thread); + return thread; +} + +void schedule() { + // printf("[schdule]\n"); + if (run_queue.head == 0) { + // printf("no thread\n"); + enable_uart_interrupt(); + core_timer_disable(); + enable_interrupt(); + return; + } + if (run_queue.head == run_queue.tail) { // idle thread + printf("left idle thread\n"); + free(run_queue.head); + run_queue.head = run_queue.tail = 0; + thread_cnt = 0; + enable_interrupt(); // need uart interrupt when go back to shell + return; + } + + do { + run_queue.tail->next = run_queue.head; + run_queue.tail = run_queue.head; + run_queue.head = run_queue.head->next; + run_queue.tail->next = 0; + } while (run_queue.head->status != THREAD_READY); + // printf("get_current()->pid = %d\n",get_current()->pid); + // printf("run_queue.head->pid = %d\n",run_queue.head->pid); + enable_interrupt(); + switch_pgd((uint64_t)(run_queue.head->pgd)); + switch_to(get_current(), run_queue.head); +} + +void idle() { + // printf("[idle]\n"); + + while (1) { + kill_zombies(); + handle_fork(); + schedule(); + if (run_queue.head == 0) break; //blcok here if any thread exist= + } +} + +void exit() { + // printf("[exit]\n"); + thread_info *cur = get_current(); + // thread_free_page(cur); + cur->status = THREAD_DEAD; + schedule(); +} + +void run_queue_push(thread_info *thread) { + if (run_queue.head == 0) { + run_queue.head = run_queue.tail = thread; + } else { + run_queue.tail->next = thread; + run_queue.tail = thread; + } +} + +void kill_zombies() { + if (run_queue.head == 0) return; + for (thread_info *ptr = run_queue.head; ptr->next != 0; ptr = ptr->next) { + for (thread_info *cur = ptr->next; + cur != 0 && (cur->status == THREAD_DEAD);) { + thread_info *tmp = cur->next; + free((void *)cur); + ptr->next = tmp; + cur = tmp; + } + if (ptr->next == 0) { + run_queue.tail = ptr; + break; + } + } +} + +void exec(const char *program_name, const char **argv) { + // printf("[exec]\n"); + thread_info *cur = get_current(); + if (cur->user_program_base == 0) { + cur->user_program_base = thread_allocate_page(cur, USER_PROGRAM_SIZE); + cur->user_stack_base = thread_allocate_page(cur, STACK_SIZE); + init_page_table(cur, &(cur->pgd)); + } + // printf("cur_pgd: 0x%p\n", (uint64_t)(cur->pgd)); + // printf("user program base: 0x%p\n", cur->user_program_base); + // printf("user stack base: 0x%p\n", cur->user_stack_base); + + cur->user_program_size = + cpio_load_user_program(program_name, cur->user_program_base); + for (uint64_t size = 0; size < cur->user_program_size; size += PAGE_SIZE) { + uint64_t virtual_addr = USER_PROGRAM_BASE + size; + uint64_t physical_addr = VA2PA(cur->user_program_base + size); + update_page_table(cur, virtual_addr, physical_addr, PD_USER_RW); + } + + // map vc memory + for (uint64_t size = 0; size < PERIPHERAL_END - PERIPHERAL_START; size += PAGE_SIZE) { + uint64_t identity_page = PERIPHERAL_START + size; + // printf("identity_page=%p\n",identity_page); + update_page_table(cur, identity_page , identity_page, PD_USER_RW); + } + + uint64_t virtual_addr = USER_STACK_BASE; + uint64_t physical_addr = VA2PA(cur->user_stack_base); + update_page_table(cur, virtual_addr, physical_addr, PD_USER_RW ); + + // el0_VA2PA(cur,USER_PROGRAM_BASE); + // el0_VA2PA(cur,0x3f000000); + // el0_VA2PA(cur,0x3f000000-1); + // el0_VA2PA(cur,0x3c25e76c); + // el0_VA2PA(cur,0x3c100000); + // el0_VA2PA(cur,0x3c000000); + // el0_VA2PA(cur,0x3c000000-1); + + uint64_t next_pgd = (uint64_t)cur->pgd; + switch_pgd(next_pgd); + + uint64_t user_sp = USER_STACK_BASE + STACK_SIZE; + // return to user program + uint64_t spsr_el1 = 0x0; // EL0t with interrupt enabled + uint64_t target_addr = USER_PROGRAM_BASE; + uint64_t target_sp = user_sp; + core_timer_enable(); + asm volatile("msr spsr_el1, %0" : : "r"(spsr_el1)); + asm volatile("msr elr_el1, %0" : : "r"(target_addr)); + asm volatile("msr sp_el0, %0" : : "r"(target_sp)); + asm volatile("eret"); +} + +void fork(uint64_t sp) { + run_queue.head->status = THREAD_FORK; + run_queue.head->trap_frame_addr = sp; + schedule(); + trap_frame_t *trap_frame = (trap_frame_t *)(get_current()->trap_frame_addr); + trap_frame->x[0] = run_queue.head->child_pid; +} + +void handle_fork() { + // printf("[handle_fork]\n"); + for (thread_info *ptr = run_queue.head->next; ptr != 0; ptr = ptr->next) { + if ((ptr->status) == THREAD_FORK) { + thread_info *child = thread_create(0); + create_child(ptr, child); + ptr->status = THREAD_READY; + child->status = THREAD_READY; + } + } +} + +void create_child(thread_info *parent, thread_info *child) { + // printf("[create_child]\n"); + disable_interrupt(); + child->user_stack_base = thread_allocate_page(child, STACK_SIZE); + child->user_program_base = thread_allocate_page(child, USER_PROGRAM_SIZE); + child->user_program_size = parent->user_program_size; + parent->child_pid = child->pid; + child->child_pid = 0; + + init_page_table(child, &(child->pgd)); + for (uint64_t size = 0; size < child->user_program_size; size += PAGE_SIZE) { + uint64_t virtual_addr = USER_PROGRAM_BASE + size; + uint64_t physical_addr = VA2PA(child->user_program_base + size); + update_page_table(child, virtual_addr, physical_addr, PD_USER_RW); + } + + for (uint64_t size = 0; size < PERIPHERAL_END - PERIPHERAL_START; size += PAGE_SIZE) { + uint64_t identity_page = PERIPHERAL_START + size; + // printf("identity_page=%p\n",identity_page); + update_page_table(child, identity_page , identity_page, PD_USER_RW); + } + uint64_t virtual_addr = USER_STACK_BASE; + uint64_t physical_addr = VA2PA(child->user_stack_base); + update_page_table(child, virtual_addr, physical_addr, PD_USER_RW); + + // el0_VA2PA(child,USER_PROGRAM_BASE); + // el0_VA2PA(child,0x3f000000); + // el0_VA2PA(child,0x3f000000-1); + // el0_VA2PA(child,0x3c25e76c); + // el0_VA2PA(child,0x3c100000); + // el0_VA2PA(child,0x3c000000); + // el0_VA2PA(child,0x3c000000-1); + + char *src, *dst; + // copy saved context in thread info + src = (char *)&(parent->context); + dst = (char *)&(child->context); + for (uint32_t i = 0; i < sizeof(cpu_context); ++i, ++src, ++dst) { + *dst = *src; + } + // copy kernel stack + src = (char *)(parent->kernel_stack_base); + dst = (char *)(child->kernel_stack_base); + for (uint32_t i = 0; i < STACK_SIZE; ++i, ++src, ++dst) { + *dst = *src; + } + // copy user stack + src = (char *)(parent->user_stack_base); + dst = (char *)(child->user_stack_base); + for (uint32_t i = 0; i < STACK_SIZE; ++i, ++src, ++dst) { + *dst = *src; + } + // copy user program + src = (char *)(parent->user_program_base); + dst = (char *)(child->user_program_base); + for (uint32_t i = 0; i < parent->user_program_size; ++i, ++src, ++dst) { + *dst = *src; + } + + // set correct address for child + uint64_t kernel_stack_base_dist = + child->kernel_stack_base - parent->kernel_stack_base; + + child->context.fp += kernel_stack_base_dist; + child->context.sp += kernel_stack_base_dist; + child->trap_frame_addr = parent->trap_frame_addr + kernel_stack_base_dist; + + // with MMU, we do not need to separate user program and stack address + // uint64_t user_stack_base_dist = + // child->user_stack_base - parent->user_stack_base; + // uint64_t user_program_base_dist = + // child->user_program_base - parent->user_program_base; + // trap_frame_t *trap_frame = (trap_frame_t *)(child->trap_frame_addr); + // trap_frame->x[29] += user_stack_base_dist; // fp (x29) + // trap_frame->x[30] += user_program_base_dist; // lr (x30) + // trap_frame->x[32] += user_program_base_dist; // elr_el1 + // trap_frame->x[33] += user_stack_base_dist; // sp_el0 + enable_interrupt(); +} +void kill (int kill_pid) +{ + if (run_queue.head == 0) return; + for (thread_info *ptr = run_queue.head; ptr->next != 0; ptr = ptr->next) { + if(ptr->pid == kill_pid){ + printf("Kill pid = %d\n",kill_pid); + ptr->status = THREAD_DEAD; + schedule(); + return; + } + } + printf("pid = %d not exist\n",kill_pid); + +} + +uint64_t thread_allocate_page(thread_info *thread, uint64_t size) { + page_frame *page_frame = buddy_allocate(size); + // printf("[thread_allocate_page]thread->page_frame_count=%d\n",thread->page_frame_count); + // printf("[thread_allocate_page]page_frame->id=%d\n",page_frame->id); + // printf("[thread_allocate_page]page_frame=%p\n",page_frame); + thread->page_frame_ids[thread->page_frame_count++] = page_frame->id; + return page_frame->addr; +} + +void thread_free_page(thread_info *thread) { + for (int i = 0; i < thread->page_frame_count; i++) { + buddy_free(&frames[thread->page_frame_ids[i]]); + } +} + +void switch_pgd(uint64_t next_pgd) { + asm volatile("dsb ish"); // ensure write has completed + asm volatile("msr ttbr0_el1, %0" + : + : "r"(next_pgd)); // switch translation based address. + asm volatile("tlbi vmalle1is"); // invalidate all TLB entries + asm volatile("dsb ish"); // ensure completion of TLB invalidatation + asm volatile("isb"); // clear pipeline +} \ No newline at end of file diff --git a/lab6/kernel/src/timer.c b/lab6/kernel/src/timer.c new file mode 100644 index 000000000..54e786faf --- /dev/null +++ b/lab6/kernel/src/timer.c @@ -0,0 +1,132 @@ +#include "timer.h" +#include "alloc.h" +#include "uart.h" +#include "utils.h" +#include "thread.h" + +void timeout_event_init() { + timeout_queue_head = 0; + timeout_queue_tail = 0; +} + +void core_timer_enable() { + asm volatile("mov x0, 1"); + asm volatile("msr cntp_ctl_el0, x0"); // enable + asm volatile("mrs x0, cntfrq_el0"); + asm volatile("msr cntp_tval_el0, x0"); // set expired time + // asm volatile("mov x0, 2"); + // asm volatile("ldr x1, =0x40000040"); // CORE0_TIMER_IRQ_CTRL + // asm volatile("str w0, [x1]"); // unmask timer interrupt + *CORE0_TIMER_IRQ_CTRL = 2; + uint64_t tmp; + asm volatile("mrs %0, cntkctl_el1" : "=r"(tmp)); + tmp |= 1; + asm volatile("msr cntkctl_el1, %0" : : "r"(tmp)); +} + +void core_timer_disable() { + asm volatile("mov x0, 0"); + asm volatile("msr cntp_ctl_el0, x0"); // disable + // asm volatile("mov x0, 0"); + // asm volatile("ldr x1, =0x40000040"); // CORE0_TIMER_IRQ_CTRL + // asm volatile("str w0, [x1]"); // unmask timer interrupt + *CORE0_TIMER_IRQ_CTRL = 0; +} + +void core_timer_handler_lowerEL_64() { // required 2 + set_expired_time(1); + // uart_puts("Time elapsed after booting: "); + // uart_int(get_current_time()); + // uart_puts("s\n"); + schedule(); +} + +void core_timer_handler_currentEL_ELx() { // elective 2 + uart_puts("Current time: "); + uart_int(get_current_time()); + uart_puts("s, "); + uart_puts("Command executed time: "); + uart_int(timeout_queue_head->register_time); + uart_puts("s, "); + uart_puts("Duration: "); + uart_int(timeout_queue_head->duration); + uart_puts("s\n"); + timeout_queue_head->callback(timeout_queue_head->args); + timeout_event *next = timeout_queue_head->next; + // free(timeout_queue_head); + if (next) { + next->prev = 0; + timeout_queue_head = next; + uint64_t next_duration = + next->register_time + next->duration - get_current_time(); + set_expired_time(next_duration); + } else { + timeout_queue_head = 0; + timeout_queue_tail = 0; + core_timer_disable(); + } +} + +void add_timer(void (*callback)(char *), char *args, uint32_t duration) { + timeout_event *new_timeout_event = + (timeout_event *)malloc(sizeof(timeout_event)); + new_timeout_event->register_time = get_current_time(); + new_timeout_event->duration = duration; + new_timeout_event->callback = callback; + for (int i = 0; i < 20; i++) { + new_timeout_event->args[i] = args[i]; + if (args[i] == '\0') break; + } + new_timeout_event->prev = 0; + new_timeout_event->next = 0; + + if (timeout_queue_head == 0) { + timeout_queue_head = new_timeout_event; + timeout_queue_tail = new_timeout_event; + core_timer_enable(); + set_expired_time(duration); + } else { + timeout_event *cur; + uint64_t timeout = + new_timeout_event->register_time + new_timeout_event->duration; + for (cur = timeout_queue_head; cur; cur = cur->next) { + if (cur->register_time + cur->duration > timeout) break; + } + + if (cur == 0) { + new_timeout_event->prev = timeout_queue_tail; + timeout_queue_tail->next = new_timeout_event; + timeout_queue_tail = new_timeout_event; + } else if (cur->prev == 0) { + new_timeout_event->next = cur; + timeout_queue_head->prev = new_timeout_event; + timeout_queue_head = new_timeout_event; + set_expired_time(duration); + } else { + new_timeout_event->prev = cur->prev; + new_timeout_event->next = cur; + cur->prev->next = new_timeout_event; + cur->prev = new_timeout_event; + } + } +} + +uint64_t get_current_time() { + uint64_t cntpct_el0, cntfrq_el0; + asm volatile("mrs %0, cntpct_el0" : "=r"(cntpct_el0)); + asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq_el0)); + return cntpct_el0 / cntfrq_el0; +} + + +void set_expired_time(uint32_t duration) { + uint64_t cntfrq_el0; + asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq_el0)); + asm volatile("msr cntp_tval_el0, %0" : : "r"(cntfrq_el0 * duration / 32)); +} + +void timer_callback(char *msg) { + uart_puts("Message: "); + uart_puts(msg); + uart_puts("\n"); +} \ No newline at end of file diff --git a/lab6/kernel/src/uart.c b/lab6/kernel/src/uart.c new file mode 100644 index 000000000..bfa6b7bf2 --- /dev/null +++ b/lab6/kernel/src/uart.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" +#include "utils.h" +#include "uart.h" +/* Auxilary mini UART registers */ +#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004)) +#define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE+0x00215040)) +#define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE+0x00215044)) +#define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE+0x00215048)) +#define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE+0x0021504C)) +#define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE+0x00215050)) +#define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE+0x00215054)) +#define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE+0x00215058)) +#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE+0x0021505C)) +#define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE+0x00215060)) +#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064)) +#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068)) +/** + * Set baud rate and characteristics (115200 8N1) and map to GPIO + */ +void uart_init() +{ + register unsigned int r; + + /* initialize UART */ + *AUX_ENABLE |=1; // enable UART1, AUX mini uart + *AUX_MU_CNTL = 0; + *AUX_MU_LCR = 3; // 8 bits + *AUX_MU_MCR = 0; + *AUX_MU_IER = 1; + // comment this line to avoid weird character + // *AUX_MU_IIR = 0xc6; // disable interrupts + *AUX_MU_BAUD = 270; // 115200 baud + /* map UART1 to GPIO pins */ + r=*GPFSEL1; + r&=~((7<<12)|(7<<15)); // gpio14, gpio15 + r|=(2<<12)|(2<<15); // alt5 + *GPFSEL1 = r; + *GPPUD = 0; // enable pins 14 and 15 + r=150; while(r--) { asm volatile("nop"); } + *GPPUDCLK0 = (1<<14)|(1<<15); + r=150; while(r--) { asm volatile("nop"); } + *GPPUDCLK0 = 0; // flush GPIO setup + *AUX_MU_CNTL = 3; // enable Tx, Rx + + read_buf_start = read_buf_end = 0; + write_buf_start = write_buf_end = 0; + enable_uart_interrupt(); +} + +/** + * Send a character + */ +void uart_send(unsigned int c) { + /* wait until we can send */ + do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x20)); + /* write the character to the buffer */ + *AUX_MU_IO=c; +} + +/** + * Receive a character + */ +char uart_getc() { + char r; + /* wait until something is in the buffer */ + do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01)); + /* read it and return */ + r=(char)(*AUX_MU_IO); + /* convert carrige return to newline */ + return r=='\r'?'\n':r; +} + +uint32_t uart_gets(char *buf, uint32_t size) { + for (int i = 0; i < size; ++i) { + buf[i] = uart_getc(); + // uart_send(buf[i]); + if (buf[i] == '\n' || buf[i] == '\r') { + // uart_send('\r'); + // buf[i] = '\0'; + return i; + } + } + return size; +} + +/** + * Display a string + */ +void uart_puts(char *s) { + while(*s) { + /* convert newline to carrige return + newline */ + if(*s=='\n') + uart_send('\r'); + uart_send(*s++); + } +} + +uint32_t uart_write(char *s, uint32_t size) { + for(int i = 0 ; i=0;c-=4) { + // get highest tetrad + n=(d>>c)&0xF; + // 0-9 => '0'-'9', 10-15 => 'A'-'F' + n+=n>9?0x37:0x30; + uart_send(n); + } +} + +void uart_int(int x) { + if (x < 0) { + uart_send('-'); + x = -x; + } + if (x >= 10) uart_int(x / 10); + uart_send(x % 10 + '0'); +} + +void enable_uart_interrupt() { *ENABLE_IRQS_1 = AUX_IRQ; } + +void disable_uart_interrupt() { *DISABLE_IRQS_1 = AUX_IRQ; } + +void assert_transmit_interrupt() { *AUX_MU_IER |= 0x2; } + +void clear_transmit_interrupt() { *AUX_MU_IER &= ~(0x2); } + +void uart_handler() { + disable_uart_interrupt(); + int is_read = (*AUX_MU_IIR & 0x4); + int is_write = (*AUX_MU_IIR & 0x2); + + if (is_read) { + // uart_puts("===== is_read =====\n"); + + char c = (char)(*AUX_MU_IO); + read_buf[read_buf_end++] = c; + if (read_buf_end == UART_BUFFER_SIZE) read_buf_end = 0; + } else if (is_write) { + // uart_puts("===== is_write =====\n"); + + while (*AUX_MU_LSR & 0x20) { + if (write_buf_start == write_buf_end) { + clear_transmit_interrupt(); + break; + } + char c = write_buf[write_buf_start++]; + *AUX_MU_IO = c; + if (write_buf_start == UART_BUFFER_SIZE) write_buf_start = 0; + } + } + enable_uart_interrupt(); +} + +char uart_async_getc() { + // wait until there are new data + // uart_puts("===== uart getc =====\n"); + while (read_buf_start == read_buf_end) { + // uart_puts("===== read_buf_start == read_buf_end =====\n"); + asm volatile("nop"); + } + char c = read_buf[read_buf_start++]; + if (read_buf_start == UART_BUFFER_SIZE) read_buf_start = 0; + // '\r' => '\n' + return c == '\r' ? '\n' : c; +} + +void uart_async_puts(char *str) { + for (int i = 0; str[i]; i++) { + if (str[i] == '\n') write_buf[write_buf_end++] = '\r'; + write_buf[write_buf_end++] = str[i]; + if (write_buf_end == UART_BUFFER_SIZE) write_buf_end = 0; + } + assert_transmit_interrupt(); +} diff --git a/lab6/kernel/src/utils.S b/lab6/kernel/src/utils.S new file mode 100644 index 000000000..894a1fdc8 --- /dev/null +++ b/lab6/kernel/src/utils.S @@ -0,0 +1,9 @@ +.globl put32 +put32: + str w1, [x0] + ret + +.globl get32 +get32: + ldr w0, [x0] + ret diff --git a/lab6/kernel/src/utils.c b/lab6/kernel/src/utils.c new file mode 100644 index 000000000..8047ee2c7 --- /dev/null +++ b/lab6/kernel/src/utils.c @@ -0,0 +1,71 @@ +// typedef unsigned long long int uint64_t; +// typedef unsigned char uint8_t; +#include "utils.h" + +uint8_t hex_to_int8(char hex){ + if(hex >= '0' && hex <= '9') + return hex-'0'; + else if(hex >= 'A' && hex <= 'Z') + return hex-'A'+10; + else if(hex >= 'a' && hex <= 'z') + return hex-'a'+10; + else + return -1; +} + +uint64_t hex_to_int64(char* num){ + uint64_t res=0; + for(int i=0; i<8; i++){ + res = (res<<4) + hex_to_int8(num[i]); + } + return res; +} + +uint64_t log2(uint64_t num) { + for (uint64_t i = 0; i < 64; i++) { + if (num == (1 << i)) return i; + } + return 0; +} +uint64_t align_up(uint64_t addr, uint64_t alignment) { + return (addr + alignment - 1) & (~(alignment - 1)); +} + +uint64_t align_up_exp(uint64_t n) { + n--; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n |= n >> 32; + n++; + return n; +} + +void delay(int num) { + while (num--) + ; +} + +uint64_t hex2int(char *hex, int len) { + uint64_t val = 0; + for (int i = 0; i < len; i++) { + // get current character then increment + uint64_t byte = *(hex + i); + if (byte >= '0' && byte <= '9') + byte = byte - '0'; + else if (byte >= 'A' && byte <= 'F') + byte = byte - 'A' + 10; + else if (byte >= 'a' && byte <= 'f') + byte = byte - 'a' + 10; + + val = (val << 4) | (byte & 0xF); + } + return val; +} + +uint32_t be2le(uint32_t x) { + return (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) | + (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); +} \ No newline at end of file diff --git a/lab6/make.sh b/lab6/make.sh new file mode 100755 index 000000000..893cdd3e6 --- /dev/null +++ b/lab6/make.sh @@ -0,0 +1,9 @@ +#bin/sh! + +make +cd kernel +make +cd .. +cd bootloader +make +cd .. diff --git a/lab6/qemu_run.sh b/lab6/qemu_run.sh new file mode 100755 index 000000000..4673212bd --- /dev/null +++ b/lab6/qemu_run.sh @@ -0,0 +1,4 @@ +# sudo chmod 777 /dev/ttyUSB0 +# python3 ./script/send_file.py -s bootloader.img +# python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/ttyUSB0 +python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/pts/14 diff --git a/lab6/run b/lab6/run new file mode 100755 index 000000000..a8d89f256 --- /dev/null +++ b/lab6/run @@ -0,0 +1,4 @@ +sudo chmod 777 /dev/ttyUSB0 +# python3 ./script/send_file.py -s bootloader.img +python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/ttyUSB0 +# python3 ./script/send_file.py -s kernel8.img -t /dev/pts/9 diff --git a/lab6/run.sh b/lab6/run.sh new file mode 100755 index 000000000..a8d89f256 --- /dev/null +++ b/lab6/run.sh @@ -0,0 +1,4 @@ +sudo chmod 777 /dev/ttyUSB0 +# python3 ./script/send_file.py -s bootloader.img +python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/ttyUSB0 +# python3 ./script/send_file.py -s kernel8.img -t /dev/pts/9 diff --git a/lab6/script/send_file.py b/lab6/script/send_file.py new file mode 100644 index 000000000..475fab1ec --- /dev/null +++ b/lab6/script/send_file.py @@ -0,0 +1,42 @@ +import argparse +from pathlib import Path +import serial + +def send_all_data(tty, data): + while len(data) > 0: + write_cnt = tty.write(data) + data = data[write_cnt:] + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + "-s", + "--src_file_pth", + type=str, + help='source file path', + default='../kernel8.img' + ) + parser.add_argument( + "-t", + "--target_pth", + nargs='?', + type=str, + help='target path', + default='/dev/ttyUSB0' + ) + args = parser.parse_args() + + with serial.Serial(args.target_pth, 115200, xonxoff=True) as tty: + magic = 0x01020304.to_bytes(4, 'big') + send_all_data(tty, magic) + + file_size = Path(args.src_file_pth).stat().st_size.to_bytes(8, 'little') + send_all_data(tty, file_size) + + with open(args.src_file_pth, 'rb') as src_file: + while True: + data = src_file.read() + if data == b'': + break + send_all_data(tty, data) + print("finish sending kernel8.img\n") \ No newline at end of file diff --git a/lab6/user/Makefile b/lab6/user/Makefile new file mode 100644 index 000000000..8961cfcb5 --- /dev/null +++ b/lab6/user/Makefile @@ -0,0 +1,32 @@ +CC = aarch64-linux-gnu-gcc +CFLAGS = -Wall -g -ffreestanding -march=armv8-a +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJCOPYFLAGS = -O binary + +BUILD_DIR = build +SRC_DIR = src +C_FILES = $(wildcard $(SRC_DIR)/*.c) +TARGET_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%) +LINKER = $(SRC_DIR)/linker.ld + +all: $(TARGET_FILES) + +clean: + rm $(BUILD_DIR)/* + +$(BUILD_DIR)/%: $(BUILD_DIR)/%.elf + $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ + cp $@ ../kernel/rootfs && \ + cd ../kernel/rootfs && \ + rm -f ../initramfs.cpio && \ + find . | cpio -o -H newc > ../initramfs.cpio + +$(BUILD_DIR)/%.elf: $(BUILD_DIR)/%.o $(BUILD_DIR)/start.asmo + $(LD) -T $(LINKER) --gc-sections -g -o $@ $< $(BUILD_DIR)/start.asmo + +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/start.asmo: $(SRC_DIR)/start.S + $(CC) $(CFLAGS) -c $< -o $@ diff --git a/lab6/user/src/fork_test.c b/lab6/user/src/fork_test.c new file mode 100644 index 000000000..cdfa47e88 --- /dev/null +++ b/lab6/user/src/fork_test.c @@ -0,0 +1,46 @@ +#include "start.h" + +int main() { + // printf("Fork Test, pid %d\n", getpid()); + print_s("Fork Test, pid "); + print_i(getpid()); + print_s("\n"); + int cnt = 1; + int ret = 0; + if ((ret = fork()) == 0) { // child + // printf("pid: %d, cnt: %d, ptr: %p\n", getpid(), cnt, &cnt); + print_s("pid: "); + print_i(getpid()); + print_s(", cnt: "); + print_i(cnt); + print_s(", ptr: "); + print_h((unsigned long long)&cnt); + print_s("\n"); + ++cnt; + fork(); + while (cnt < 5) { + // printf("pid: %d, cnt: %d, ptr: %p\n", getpid(), cnt, &cnt); + print_s("pid: "); + print_i(getpid()); + print_s(", cnt: "); + print_i(cnt); + print_s(", ptr: "); + print_h((unsigned long long)&cnt); + print_s("\n"); + delay(100000000); + ++cnt; + } + } else { + // printf("parent here, pid %d, child %d\n", getpid(), ret); + for(int i = 0 ; i < 5;i++){ + print_s("parent here, pid: "); + print_i(getpid()); + print_s(", child: "); + print_i(ret); + print_s("\n"); + delay(100000000); + } + } + // while(1); + return 0; +} \ No newline at end of file diff --git a/lab6/user/src/linker.ld b/lab6/user/src/linker.ld new file mode 100644 index 000000000..8e6ab1c9d --- /dev/null +++ b/lab6/user/src/linker.ld @@ -0,0 +1,17 @@ +SECTIONS +{ + . = 0x80000; + + .text : { KEEP(*(.text.boot)) *(.text .text.*) } + + .rodata : { *(.rodata .rodata.*) } + + .data : { *(.data .data.*) } + + .bss : { + *(.bss .bss.*) + *(COMMON) + } + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} \ No newline at end of file diff --git a/lab6/user/src/mailbox_test.c b/lab6/user/src/mailbox_test.c new file mode 100644 index 000000000..7b5548da7 --- /dev/null +++ b/lab6/user/src/mailbox_test.c @@ -0,0 +1,63 @@ +#include "start.h" + +int main() { + unsigned int __attribute__((aligned(16))) mbox[8]; + + // get serail number + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETSERIAL; // get serial number command + mbox[3] = 8; // buffer size + mbox[4] = 8; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + print_s("\n"); + if (mbox_call(MBOX_CH_PROP,mbox)) { + print_s("serial number is: "); + print_h(mbox[6]); + print_h(mbox[5]); + print_s("\n"); + } + // get board revision + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETBDVS; // get board revision + mbox[3] = 4; // buffer size + mbox[4] = 4; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + if (mbox_call(MBOX_CH_PROP,mbox)) { + print_s("board revision is: "); + print_h(mbox[6]); + print_h(mbox[5]); + print_s("\n"); + } + + // get arm memory + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETARMMEM; // get arm memory info + mbox[3] = 8; // buffer size + mbox[4] = 8; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + if (mbox_call(MBOX_CH_PROP,mbox)) { + print_s("arm base addr: "); + print_h(mbox[5]); + print_s("\n"); + print_s("arm addr size: "); + print_h(mbox[6]); + print_s("\n"); + } + // while(1); + return 0; +} \ No newline at end of file diff --git a/lab6/user/src/mbox.h b/lab6/user/src/mbox.h new file mode 100644 index 000000000..1de89d020 --- /dev/null +++ b/lab6/user/src/mbox.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/* a properly aligned buffer */ +extern unsigned int mbox[8]; + +#define MBOX_REQUEST 0 + +/* channels */ +#define MBOX_CH_POWER 0 +#define MBOX_CH_FB 1 +#define MBOX_CH_VUART 2 +#define MBOX_CH_VCHIQ 3 +#define MBOX_CH_LEDS 4 +#define MBOX_CH_BTNS 5 +#define MBOX_CH_TOUCH 6 +#define MBOX_CH_COUNT 7 +#define MBOX_CH_PROP 8 + +/* tags */ +#define MBOX_TAG_SETPOWER 0x28001 +#define MBOX_TAG_SETCLKRATE 0x38002 +#define MBOX_TAG_GETSERIAL 0x10004 +#define MBOX_TAG_GETBDVS 0x00010002 +#define MBOX_TAG_GETARMMEM 0x00010005 + +#define MBOX_TAG_LAST 0 + +int mbox_call(unsigned char ch, unsigned int* mbox); diff --git a/lab6/user/src/my_test.c b/lab6/user/src/my_test.c new file mode 100644 index 000000000..fec737a7e --- /dev/null +++ b/lab6/user/src/my_test.c @@ -0,0 +1,12 @@ +#include "start.h" +int main(int argc, char **argv) { + for(int i = 0 ; i<10 ; i++){ + print_s("Test1, pid "); + print_i(getpid()); + print_s("\n"); + delay(100000000); + // asm volatile("mov x8, #9"); + // asm volatile("svc 0"); + } + return 0; +} \ No newline at end of file diff --git a/lab6/user/src/my_test2.c b/lab6/user/src/my_test2.c new file mode 100644 index 000000000..ccef819a3 --- /dev/null +++ b/lab6/user/src/my_test2.c @@ -0,0 +1,12 @@ +#include "start.h" +int main(int argc, char **argv) { + for(int i = 0 ; i<10 ; i++){ + print_s("Test2, pid "); + print_i(getpid()); + print_s("\n"); + delay(100000000); + // asm volatile("mov x8, #9"); + // asm volatile("svc 0"); + } + return 0 ; +} \ No newline at end of file diff --git a/lab6/user/src/start.S b/lab6/user/src/start.S new file mode 100644 index 000000000..aa493e033 --- /dev/null +++ b/lab6/user/src/start.S @@ -0,0 +1,55 @@ +.section ".text.boot" + +.global _start + +_start: + bl main + b exit + +.section ".text" + +.global uart_read +.global uart_write +.global getpid +.global fork +.global exec +.global exit +.global mbox_call + +getpid: + mov x8, #0 + svc 0 + ret + +uart_read: + mov x8, #1 + svc 0 + ret + +uart_write: + mov x8, #2 + svc 0 + ret + +exec: + mov x8, #3 + svc 0 + ret + +fork: + mov x8, #4 + svc 0 + ret + +exit: + mov x8, #5 + svc 0 + ret + +mbox_call: + mov x8, #6 + svc 0 + ret + + + diff --git a/lab6/user/src/start.h b/lab6/user/src/start.h new file mode 100644 index 000000000..7afe915f5 --- /dev/null +++ b/lab6/user/src/start.h @@ -0,0 +1,78 @@ +#ifndef START_H +#define START_H + +#include +#include + +unsigned long uart_read(char buf[], size_t size); +unsigned long uart_write(const char buf[], size_t size); +int getpid(); +unsigned long fork(); +int exec(const char *name, char *const argv[]); +void exit(); + +void delay(int n) { + while (n--) + ; +} + +int strlen(const char *s) { + int len = 0; + while (s[len] != '\0') { + len++; + } + return len; +} + +void print_c(char c) { + char s[2]; + s[0] = c; + s[1] = '\0'; + uart_write(s, strlen(s)); +} + +void print_s(char *s) { uart_write(s, strlen(s)); } + +void print_i(int x) { + if (x < 0) { + print_c('-'); + x = -x; + } + if (x >= 10) print_i(x / 10); + print_c(x % 10 + '0'); +} + +void print_h(unsigned long x) { + print_s("0x"); + for (int c = 28; c >= 0; c -= 4) { + int n = (x >> c) & 0xF; + n += n > 9 ? 'A' - 10 : '0'; + print_c(n); + } +} + +#define MBOX_REQUEST 0 + +/* channels */ +#define MBOX_CH_POWER 0 +#define MBOX_CH_FB 1 +#define MBOX_CH_VUART 2 +#define MBOX_CH_VCHIQ 3 +#define MBOX_CH_LEDS 4 +#define MBOX_CH_BTNS 5 +#define MBOX_CH_TOUCH 6 +#define MBOX_CH_COUNT 7 +#define MBOX_CH_PROP 8 + +/* tags */ +#define MBOX_TAG_SETPOWER 0x28001 +#define MBOX_TAG_SETCLKRATE 0x38002 +#define MBOX_TAG_GETSERIAL 0x10004 +#define MBOX_TAG_GETBDVS 0x00010002 +#define MBOX_TAG_GETARMMEM 0x00010005 + +#define MBOX_TAG_LAST 0 + +int mbox_call(unsigned char ch, unsigned int* mbox); + +#endif \ No newline at end of file diff --git a/lab6/user/src/svc_test.c b/lab6/user/src/svc_test.c new file mode 100644 index 000000000..a3fbfe8dd --- /dev/null +++ b/lab6/user/src/svc_test.c @@ -0,0 +1,7 @@ +int main() { + for (int i = 0; i < 5; i++) { + asm volatile("svc 0"); + } + + return 0; +} \ No newline at end of file diff --git a/lab6/user/src/user_program.S b/lab6/user/src/user_program.S new file mode 100644 index 000000000..838323763 --- /dev/null +++ b/lab6/user/src/user_program.S @@ -0,0 +1,11 @@ +.section ".text" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b \ No newline at end of file diff --git a/lab7/bootloader/Makefile b/lab7/bootloader/Makefile new file mode 100644 index 000000000..cff2e3c2a --- /dev/null +++ b/lab7/bootloader/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) 2018 bzt (bztsrc@github) +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, copy, +# modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +# + +CFILE = $(wildcard *.c) +ASMFILE = $(wildcard *.S) +OBJS = $(CFILE:.c=_c.o) +OBJS += $(ASMFILE:.S=_s.o) +CFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -fno-stack-protector -Iinclude -Iinclude + +all: kernel8.img + +%_s.o: %.S + aarch64-elf-gcc $(CFLAGS) -c $< -o $@ + +%_c.o: %.c + aarch64-elf-gcc $(CFLAGS) -c $< -o $@ + +kernel8.img: $(OBJS) + aarch64-elf-ld -nostdlib -nostartfiles $(OBJS) -T link.ld -o bootloader.elf + aarch64-elf-objcopy -O binary bootloader.elf bootloader.img + +clean: + rm kernel8.elf *.o >/dev/null 2>/dev/null || true + +run: + qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial null -serial stdio diff --git a/lab7/bootloader/bootloader.elf b/lab7/bootloader/bootloader.elf new file mode 100755 index 000000000..74f2d52e7 Binary files /dev/null and b/lab7/bootloader/bootloader.elf differ diff --git a/lab7/bootloader/bootloader.img b/lab7/bootloader/bootloader.img new file mode 100755 index 000000000..e777a0053 Binary files /dev/null and b/lab7/bootloader/bootloader.img differ diff --git a/lab7/bootloader/include/mini_uart.h b/lab7/bootloader/include/mini_uart.h new file mode 100644 index 000000000..aebc2c5a2 --- /dev/null +++ b/lab7/bootloader/include/mini_uart.h @@ -0,0 +1,9 @@ +#ifndef _MINI_UART_H +#define _MINI_UART_H + +void uart_init(void); +char uart_getc(void); +void uart_putc(char c); +void uart_puts(char* str); + +#endif \ No newline at end of file diff --git a/lab7/bootloader/include/mm.h b/lab7/bootloader/include/mm.h new file mode 100644 index 000000000..119624a2b --- /dev/null +++ b/lab7/bootloader/include/mm.h @@ -0,0 +1,17 @@ +#ifndef _MM_H +#define _MM_H + +#define PAGE_SHIFT 12 +#define TABLE_SHIFT 9 +#define SECTION_SHIFT (PAGE_SHIFT + TABLE_SHIFT) + +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define SECTION_SIZE (1 << SECTION_SHIFT) + +#define LOW_MEMORY (2 * SECTION_SIZE) + +#ifndef __ASSEMBLER__ +void memzero(unsigned long src, unsigned long n); +#endif + +#endif \ No newline at end of file diff --git a/lab7/bootloader/include/peripherals/base.h b/lab7/bootloader/include/peripherals/base.h new file mode 100644 index 000000000..d7eb1f9b5 --- /dev/null +++ b/lab7/bootloader/include/peripherals/base.h @@ -0,0 +1,6 @@ +#ifndef _PER_BASE_H_ +#define _PER_BASE_H_ + +#define PHY_BASE_ADDR 0x3F000000 + +#endif \ No newline at end of file diff --git a/lab7/bootloader/include/peripherals/gpio.h b/lab7/bootloader/include/peripherals/gpio.h new file mode 100644 index 000000000..1132dae95 --- /dev/null +++ b/lab7/bootloader/include/peripherals/gpio.h @@ -0,0 +1,12 @@ +#ifndef _PER_GPIO_H +#define _PER_GPIO_H + +#include "peripherals/base.h" + +#define GPFSEL1 (PHY_BASE_ADDR + 0x00200004) +#define GPSET0 (PHY_BASE_ADDR + 0x0020001C) +#define GPCLR0 (PHY_BASE_ADDR + 0x00200028) +#define GPPUD (PHY_BASE_ADDR + 0x00200094) +#define GPPUDCLK0 (PHY_BASE_ADDR + 0x00200098) + +#endif \ No newline at end of file diff --git a/lab7/bootloader/include/peripherals/mini_uart.h b/lab7/bootloader/include/peripherals/mini_uart.h new file mode 100644 index 000000000..c08d34831 --- /dev/null +++ b/lab7/bootloader/include/peripherals/mini_uart.h @@ -0,0 +1,18 @@ +#ifndef _PER_MINI_UART_H_ +#define _PER_MINI_UART_H_ + +#include "peripherals/base.h" +#define AUX_ENABLES (PHY_BASE_ADDR + 0x00215004) +#define AUX_MU_IO_REG (PHY_BASE_ADDR + 0x00215040) +#define AUX_MU_IER_REG (PHY_BASE_ADDR + 0x00215044) +#define AUX_MU_IIR_REG (PHY_BASE_ADDR + 0x00215048) +#define AUX_MU_LCR_REG (PHY_BASE_ADDR + 0x0021504C) +#define AUX_MU_MCR_REG (PHY_BASE_ADDR + 0x00215050) +#define AUX_MU_LSR_REG (PHY_BASE_ADDR + 0x00215054) +#define AUX_MU_MSR_REG (PHY_BASE_ADDR + 0x00215058) +#define AUX_MU_SCRATCH (PHY_BASE_ADDR + 0x0021505C) +#define AUX_MU_CNTL_REG (PHY_BASE_ADDR + 0x00215060) +#define AUX_MU_STAT_REG (PHY_BASE_ADDR + 0x00215064) +#define AUX_MU_BAUD_REG (PHY_BASE_ADDR + 0x00215068) + +#endif \ No newline at end of file diff --git a/lab7/bootloader/include/shell.h b/lab7/bootloader/include/shell.h new file mode 100644 index 000000000..d588b1de9 --- /dev/null +++ b/lab7/bootloader/include/shell.h @@ -0,0 +1,26 @@ +#ifndef _SHELL_H +#define _SHELL_H + +void buffer_clear(); +void execute_command(char *); +void init_shell(); + +void print_input_prompt(); +void get_input(); + +void del_key(); +void left_key(); +void right_key(); +void up_key(); +void down_key(); + +void simple_shell(); + +void shell_hello(); +void shell_help(); +void shell_reboot(); +void shell_boot_uart(); + +void shell_ls(); + +#endif \ No newline at end of file diff --git a/lab7/bootloader/include/stdint.h b/lab7/bootloader/include/stdint.h new file mode 100644 index 000000000..ebc26e483 --- /dev/null +++ b/lab7/bootloader/include/stdint.h @@ -0,0 +1,18 @@ +#ifndef _STDINT_H +#define _STDINT_H + +typedef unsigned long long int uint64_t; +typedef signed long long int int64_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +typedef unsigned short int uint16_t; +typedef signed short int int16_t; + +typedef unsigned char uint8_t; +typedef signed char int8_t; + +uint8_t hex_to_int64(char*); +uint64_t hex_to_int8(char); +#endif \ No newline at end of file diff --git a/lab7/bootloader/include/str_tool.h b/lab7/bootloader/include/str_tool.h new file mode 100644 index 000000000..3d5018e36 --- /dev/null +++ b/lab7/bootloader/include/str_tool.h @@ -0,0 +1,24 @@ +#ifndef _STR_TOOL_H +#define _STR_TOOL_H +#include "stdint.h" + +typedef struct { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} cpio_newc_header; + +int strcmp(char*, char*); +char* itoa(int64_t, int); +#endif \ No newline at end of file diff --git a/lab7/bootloader/include/utils.h b/lab7/bootloader/include/utils.h new file mode 100644 index 000000000..99dfeecc6 --- /dev/null +++ b/lab7/bootloader/include/utils.h @@ -0,0 +1,8 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +void delay(unsigned long); +void put32(unsigned long, unsigned int); +unsigned int get32(unsigned long); + +#endif \ No newline at end of file diff --git a/lab7/bootloader/link.ld b/lab7/bootloader/link.ld new file mode 100644 index 000000000..dfbf24cf2 --- /dev/null +++ b/lab7/bootloader/link.ld @@ -0,0 +1,13 @@ +SECTIONS +{ + . = 0x50000; + .text : { KEEP(*(.text.boot)) *(.text) } + .rodata : { *(.rodata) } + .data : { *(.data) } + + . = ALIGN(0x8); + bss_begin = .; + .bss : { *(.bss*) } + bss_end = .; + _end = .; +} diff --git a/lab7/bootloader/main.c b/lab7/bootloader/main.c new file mode 100644 index 000000000..46afb4dfb --- /dev/null +++ b/lab7/bootloader/main.c @@ -0,0 +1,31 @@ +#include "mini_uart.h" +#include "utils.h" +#include "stdint.h" + +union large_int_by_byte{ + uint8_t int_by_byte[8]; + uint64_t larg_int; +}; + +void boot_main(){ + uart_init(); + + union large_int_by_byte program; + volatile uint8_t *program_addr = (volatile uint8_t *)0x80000; + + // read dirty message until end + while(1) { + uint8_t data; + data = uart_getc(); + if(data==4)break; + } + + // read kernel size + for(int i=0; i<8; i++) + program.int_by_byte[i] = uart_getc(); + + for(uint64_t offset=0; offset= '0' && hex <= '9') + return hex-'0'; + else if(hex >= 'A' && hex <= 'Z') + return hex-'A'+10; + else if(hex >= 'a' && hex <= 'z') + return hex-'a'+10; + else + return -1; +} + +uint64_t hex_to_int64(char* num){ + uint64_t res=0; + for(int i=0; i<8; i++){ + res = (res<<4) + hex_to_int8(num[i]); + } + return res; +} \ No newline at end of file diff --git a/lab7/bootloader/str_tool.c b/lab7/bootloader/str_tool.c new file mode 100644 index 000000000..cb955f297 --- /dev/null +++ b/lab7/bootloader/str_tool.c @@ -0,0 +1,23 @@ +#include "stdint.h" + +int strcmp(char *s1, char *s2){ + while(*s1!='\0' && *s2!='\0' && *s1==*s2){ + s1 += 1; + s2 += 1; + } + return *s1 - *s2; +} + +char* itoa(int64_t val, int base){ + static char buf[32] = {0}; + int i = 30; + if (val == 0) { + buf[i] = '0'; + return &buf[i]; + } + + for (; val && i; --i, val /= base) + buf[i] = "0123456789abcdef"[val % base]; + + return &buf[i + 1]; +} \ No newline at end of file diff --git a/lab7/bootloader/utils.S b/lab7/bootloader/utils.S new file mode 100644 index 000000000..e735f1dc7 --- /dev/null +++ b/lab7/bootloader/utils.S @@ -0,0 +1,15 @@ +.globl put32 +put32: + str w1, [x0] + ret + +.globl get32 +get32: + ldr w0, [x0] + ret + +.globl delay +delay: + subs x0, x0, #1 + bne delay + ret \ No newline at end of file diff --git a/lab7/bootloader/utils/mini_uart.c b/lab7/bootloader/utils/mini_uart.c new file mode 100644 index 000000000..46ca9cfe0 --- /dev/null +++ b/lab7/bootloader/utils/mini_uart.c @@ -0,0 +1,47 @@ +#include "utils.h" +#include "peripherals/gpio.h" +#include "peripherals/mini_uart.h" + +void uart_init(){ + unsigned int selector; + + selector = get32(GPFSEL1); + selector &= ~(7<<12); // clean gpio 14 + selector |= 2<<12; // set alt5 at gpio14 + selector &= ~(7<<15); // clean gpio 15 + selector |= 2<<15; // set alt5 at gpio 15 + put32(GPFSEL1, selector); + + put32(GPPUD, 0); // disable pull-up/down + delay(150); // wait 150 cycles + put32(GPPUDCLK0, (1<<14)|(1<<15)); // only modify GPIO 14 and 15 + delay(150); + put32(GPPUDCLK0, 0); // remove the clock + + put32(AUX_ENABLES, 1); // enable mini UART + put32(AUX_MU_CNTL_REG, 0); // Disable transmitter and receiver during configuration + put32(AUX_MU_IER_REG, 0); // Disable interrupt + put32(AUX_MU_LCR_REG, 3); // Set the data size to 8 bit + put32(AUX_MU_MCR_REG, 0); // Don’t need auto flow control + put32(AUX_MU_BAUD_REG, 270); // Set baud rate to 115200 + + put32(AUX_MU_IIR_REG, 6); // No FIFO + put32(AUX_MU_CNTL_REG, 3); // Enable the transmitter and receiver +} + +void uart_putc(char c){ + while(!(get32(AUX_MU_LSR_REG)&0x20)); + put32(AUX_MU_IO_REG, c); +} + +char uart_getc(void){ + while(!(get32(AUX_MU_LSR_REG)&0x01)); + return get32(AUX_MU_IO_REG); +} + +void uart_puts(char* str){ + while(*str){ + uart_putc(*str); + str += 1; + } +} \ No newline at end of file diff --git a/lab7/bootloader/utils/mm.S b/lab7/bootloader/utils/mm.S new file mode 100644 index 000000000..f9b279e14 --- /dev/null +++ b/lab7/bootloader/utils/mm.S @@ -0,0 +1,6 @@ +.globl memzero +memzero: + str xzr, [x0], #8 + subs x1, x1, #8 + b.gt memzero + ret \ No newline at end of file diff --git a/lab7/bootloader/utils/stdint.c b/lab7/bootloader/utils/stdint.c new file mode 100644 index 000000000..c41cc43ea --- /dev/null +++ b/lab7/bootloader/utils/stdint.c @@ -0,0 +1,21 @@ +typedef unsigned long long int uint64_t; +typedef unsigned char uint8_t; + +uint8_t hex_to_int8(char hex){ + if(hex >= '0' && hex <= '9') + return hex-'0'; + else if(hex >= 'A' && hex <= 'Z') + return hex-'A'+10; + else if(hex >= 'a' && hex <= 'z') + return hex-'a'+10; + else + return -1; +} + +uint64_t hex_to_int64(char* num){ + uint64_t res=0; + for(int i=0; i<8; i++){ + res = (res<<4) + hex_to_int8(num[i]); + } + return res; +} \ No newline at end of file diff --git a/lab7/bootloader/utils/str_tool.c b/lab7/bootloader/utils/str_tool.c new file mode 100644 index 000000000..cb955f297 --- /dev/null +++ b/lab7/bootloader/utils/str_tool.c @@ -0,0 +1,23 @@ +#include "stdint.h" + +int strcmp(char *s1, char *s2){ + while(*s1!='\0' && *s2!='\0' && *s1==*s2){ + s1 += 1; + s2 += 1; + } + return *s1 - *s2; +} + +char* itoa(int64_t val, int base){ + static char buf[32] = {0}; + int i = 30; + if (val == 0) { + buf[i] = '0'; + return &buf[i]; + } + + for (; val && i; --i, val /= base) + buf[i] = "0123456789abcdef"[val % base]; + + return &buf[i + 1]; +} \ No newline at end of file diff --git a/lab7/bootloader/utils/utils.S b/lab7/bootloader/utils/utils.S new file mode 100644 index 000000000..e735f1dc7 --- /dev/null +++ b/lab7/bootloader/utils/utils.S @@ -0,0 +1,15 @@ +.globl put32 +put32: + str w1, [x0] + ret + +.globl get32 +get32: + ldr w0, [x0] + ret + +.globl delay +delay: + subs x0, x0, #1 + bne delay + ret \ No newline at end of file diff --git a/lab7/config.txt b/lab7/config.txt new file mode 100644 index 000000000..261480683 --- /dev/null +++ b/lab7/config.txt @@ -0,0 +1,4 @@ +kernel_address=0x60000 +kernel=bootloader.img +arm_64bit=1 +initramfs initramfs.cpio 0x8000000 \ No newline at end of file diff --git a/lab7/kernel/Makefile b/lab7/kernel/Makefile new file mode 100644 index 000000000..54fc6c2c5 --- /dev/null +++ b/lab7/kernel/Makefile @@ -0,0 +1,49 @@ +CC = aarch64-linux-gnu-gcc +CFLAGS = -Iinclude -Wall -nostdlib -nostartfiles -ffreestanding +# ASMFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJCOPYFLAGS = -O binary + +QEMU = qemu-system-aarch64 + +BUILD_DIR = build +SRC_DIR = src + +all: initramfs.cpio kernel8.img + +initramfs.cpio: + cd rootfs; find . | cpio -o -H newc > ../initramfs.cpio; cd ..; + +clean: + rm $(BUILD_DIR)/* initramfs.cpio + +$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c + mkdir -p $(@D) + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S + $(CC) $(ASMFLAGS) -c $< -o $@ + +C_FILES = $(wildcard $(SRC_DIR)/*.c) +ASM_FILES = $(wildcard $(SRC_DIR)/*.S) +OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o) +OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o) + +kernel8.elf: $(SRC_DIR)/linker.ld $(OBJ_FILES) + $(LD) -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf $(OBJ_FILES) + +kernel8.img: kernel8.elf + $(OBJCOPY) $(OBJCOPYFLAGS) $(BUILD_DIR)/kernel8.elf $(BUILD_DIR)/kernel8.img + +run: + $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -display none -serial null -serial stdio -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + +run1: + killall -9 qemu-system-aarch64 + $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -display vnc=127.0.0.4:0 -serial null -serial stdio -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + + +debug: + killall -9 qemu-system-aarch64 + $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -serial null -serial stdio -display none -S -s -initrd initramfs.cpio \ No newline at end of file diff --git a/lab7/kernel/gdb_file b/lab7/kernel/gdb_file new file mode 100644 index 000000000..8e9744669 --- /dev/null +++ b/lab7/kernel/gdb_file @@ -0,0 +1,2 @@ +file build/kernel8.elf +target remote :1234 \ No newline at end of file diff --git a/lab7/kernel/include/alloc.h b/lab7/kernel/include/alloc.h new file mode 100644 index 000000000..ff3819985 --- /dev/null +++ b/lab7/kernel/include/alloc.h @@ -0,0 +1,42 @@ +#pragma once +#include "utils.h" +#include +#define PAGE_BASE_ADDR ((uint64_t)0x10000000) +#define PAGE_END_ADDR ((uint64_t)0x20000000) +#define PAGE_SIZE ((uint64_t)(4 * kb)) +#define MAX_PAGE_NUM \ + ((uint64_t)((PAGE_END_ADDR - PAGE_BASE_ADDR) / PAGE_SIZE)) // 65536 +#define MAX_FRAME_ORDER 16 // 2^16 = 65536 +#define FRAME_LIST_NUM (MAX_FRAME_ORDER + 1) + +typedef struct PageFrame { + int id; + int order; + int is_allocated; + uint64_t addr; + struct PageFrame *next; +} page_frame; + +typedef struct DMAHeader { + uint64_t total_size; + uint64_t used_size; + int is_allocated; + page_frame *frame_ptr; + struct DMAHeader *prev, *next; +} dma_header; + +page_frame frames[MAX_PAGE_NUM]; +page_frame *free_frame_lists[FRAME_LIST_NUM], *used_frame_lists[FRAME_LIST_NUM]; + +dma_header *free_dma_list; + +void buddy_init(); +void buddy_test(); +page_frame *buddy_allocate(uint64_t size); +void buddy_free(page_frame *frame); +void buddy_unlink(int index, int type); +void print_frame_lists(); +void dma_test(); +void *malloc(uint64_t size); +void free(void *ptr); +void print_dma_list(); diff --git a/lab7/kernel/include/cpio.h b/lab7/kernel/include/cpio.h new file mode 100644 index 000000000..b791d6f0e --- /dev/null +++ b/lab7/kernel/include/cpio.h @@ -0,0 +1,66 @@ +#pragma once + +#include +#include +#include +#include "utils.h" + +#define RAMFS_ADDR 0x8000000 +#define CPIO_MAGIC "070701" +#define CPIO_END "TRAILER!!!" + +#define MAX_FILES_IN_DIR 16 +#define CPIOFS_BUF_SIZE (500 * kb) + +typedef struct { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} cpio_newc_header; + +void cpio_ls(); +void cpio_cat(char *filename); +uint32_t cpio_load_user_program(const char *target_program, + uint64_t target_addr); +void cpio_populate_rootfs(); + +struct cpiofs_file { + size_t size; + char *buffer; +}; + +struct cpiofs_fentry { + char name[20]; + FILE_TYPE type; + struct vnode* vnode; + struct vnode* parent_vnode; + struct cpiofs_fentry* child[MAX_FILES_IN_DIR]; + struct cpiofs_file* file; +}; + +struct vnode_operations* cpiofs_v_ops; +struct file_operations* cpiofs_f_ops; + +void cpiofs_init(); +void cpiofs_set_fentry(struct cpiofs_fentry* fentry, const char* component_name, + struct cpiofs_file* file, FILE_TYPE type, struct vnode* vnode); +int cpiofs_setup_mount(struct filesystem* fs, struct mount* mount); +int cpiofs_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name); +int cpiofs_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type); +int cpiofs_set_parent(struct vnode* child_node, struct vnode* parent_vnode); +int cpiofs_write(struct file* file, const void* buf, size_t len); +int cpiofs_read(struct file* file, void* buf, size_t len); +int cpiofs_list(struct file* file, void* buf, int index); diff --git a/lab7/kernel/include/delays.h b/lab7/kernel/include/delays.h new file mode 100644 index 000000000..ebbeb94ce --- /dev/null +++ b/lab7/kernel/include/delays.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +void wait_cycles(unsigned int n); +void wait_msec(unsigned int n); +unsigned long get_system_timer(); +void wait_msec_st(unsigned int n); diff --git a/lab7/kernel/include/device.h b/lab7/kernel/include/device.h new file mode 100644 index 000000000..687f856c5 --- /dev/null +++ b/lab7/kernel/include/device.h @@ -0,0 +1,65 @@ +#pragma once +#include +#include "gpio.h" +#include "utils.h" +#include "vfs.h" +#include "uart.h" + +#define MAX_DEVICE_IN_DIR 16 + +typedef enum { DEV_ROOT, DEV_UART, DEV_NONE, DEV_FB } DEV_TYPE; + +struct device_fentry { + char name[20]; + //FILE_TYPE type; // all FILE_REGULAR??? + DEV_TYPE type; + struct vnode* vnode; + struct vnode* parent_vnode; + struct device_fentry* child[MAX_DEVICE_IN_DIR]; +}; + +struct framebuffer_info { + unsigned int width; + unsigned int height; + unsigned int pitch; + unsigned int isrgb; +}; + +struct vnode_operations* device_v_ops; +struct file_operations* device_f_ops; + +void device_init(); +void device_set_fentry(struct device_fentry* fentry, const char* component_name, + struct vnode* vnode, DEV_TYPE type); +int device_setup_mount(struct filesystem* fs, struct mount* mount); +int device_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name); +int device_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type); +int _device_create(struct vnode* dir_node, + const char* component_name, DEV_TYPE type); +int device_set_parent(struct vnode* child_node, struct vnode* parent_vnode); +int device_write(struct file* file, const void* buf, size_t len); +int device_read(struct file* file, void* buf, size_t len); +void device_list(struct vnode* dir); + +void root_init(); + +struct vnode_operations* uartfs_v_ops; +struct file_operations* uartfs_f_ops; +void uartfs_init(); +int uartfs_read(struct file* file, void* buf, size_t len); +int uartfs_write(struct file* file, const void* buf, size_t len); + + +struct vnode_operations* fb_v_ops; +struct file_operations* fb_f_ops; +void fb_init(); +int fb_write(struct file* file, const void* buf, size_t len); + + +//framebuffer syscall +long lseek64(int fd, long offset, int whence); +int ioctl(int fd, unsigned long request, struct framebuffer_info* info ); +unsigned char *lfb; /* raw frame buffer address */ +unsigned int isrgb; /* dimensions and channel order */ diff --git a/lab7/kernel/include/dtb.h b/lab7/kernel/include/dtb.h new file mode 100644 index 000000000..f4dfc9163 --- /dev/null +++ b/lab7/kernel/include/dtb.h @@ -0,0 +1,38 @@ +#pragma once + +#include "utils.h" + +#define FDT_BEGIN_NODE (0x00000001) +#define FDT_END_NODE (0x00000002) +#define FDT_PROP (0x00000003) +#define FDT_NOP (0x00000004) +#define FDT_END (0x00000009) + +typedef struct { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +} fdt_header; + +void mailbox_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void gpio_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void rtx3080ti_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void default_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +int check_compatibility(uint64_t struct_addr, uint64_t strings_addr, + char *compatible_name); + +void dtb_print(int all); +void dtb_parse(uint64_t struct_addr, uint64_t strings_addr, + void (*callback)(uint64_t, uint64_t, int)); +uint64_t ignore_current_node(uint64_t struct_addr, uint64_t strings_addr); +uint64_t print_node(uint64_t struct_addr, uint64_t strings_addr, int depth); +uint64_t print_property(uint64_t struct_addr, uint64_t strings_addr, int depth); +uint32_t dtb_read_int(uint64_t addr_ptr); +// char *dtb_read_string(uint64_t *addr_ptr); \ No newline at end of file diff --git a/lab7/kernel/include/exception.h b/lab7/kernel/include/exception.h new file mode 100644 index 000000000..b6e34b279 --- /dev/null +++ b/lab7/kernel/include/exception.h @@ -0,0 +1,12 @@ +#pragma once + +#include "gpio.h" +#include "utils.h" +#include +void sync_handler_currentEL_ELx(); +void sync_handler_lowerEL_64(uint64_t sp_addr); +void irq_handler_currentEL_ELx(); +void irq_handler_lowerEL_64(); +void default_handler(); +void enable_interrupt(); +void disable_interrupt(); \ No newline at end of file diff --git a/lab7/kernel/include/gpio.h b/lab7/kernel/include/gpio.h new file mode 100644 index 000000000..52fa671d0 --- /dev/null +++ b/lab7/kernel/include/gpio.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#define MMIO_BASE 0x3F000000 + +#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000)) +#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004)) +#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008)) +#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C)) +#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010)) +#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014)) +#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C)) +#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020)) +#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028)) +#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034)) +#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038)) +#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040)) +#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044)) +#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064)) +#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068)) +#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094)) +#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098)) +#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C)) diff --git a/lab7/kernel/include/math.h b/lab7/kernel/include/math.h new file mode 100644 index 000000000..b3c6a317f --- /dev/null +++ b/lab7/kernel/include/math.h @@ -0,0 +1,6 @@ +#ifndef MATH_H +#define MATH_H + +int pow(int base, int exponent); + +#endif \ No newline at end of file diff --git a/lab7/kernel/include/mbox.h b/lab7/kernel/include/mbox.h new file mode 100644 index 000000000..b08665886 --- /dev/null +++ b/lab7/kernel/include/mbox.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/* a properly aligned buffer */ +extern unsigned int mbox[36]; + +#define MBOX_REQUEST 0 + +/* channels */ +#define MBOX_CH_POWER 0 +#define MBOX_CH_FB 1 +#define MBOX_CH_VUART 2 +#define MBOX_CH_VCHIQ 3 +#define MBOX_CH_LEDS 4 +#define MBOX_CH_BTNS 5 +#define MBOX_CH_TOUCH 6 +#define MBOX_CH_COUNT 7 +#define MBOX_CH_PROP 8 + +/* tags */ +#define MBOX_TAG_SETPOWER 0x28001 +#define MBOX_TAG_SETCLKRATE 0x38002 +#define MBOX_TAG_GETSERIAL 0x10004 +#define MBOX_TAG_GETBDVS 0x00010002 +#define MBOX_TAG_GETARMMEM 0x00010005 + +#define MBOX_TAG_LAST 0 + +int mbox_call(unsigned char ch, unsigned int* mbox); diff --git a/lab7/kernel/include/power.h b/lab7/kernel/include/power.h new file mode 100644 index 000000000..4216fa556 --- /dev/null +++ b/lab7/kernel/include/power.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +void power_off(); +void reset(); diff --git a/lab7/kernel/include/printf.h b/lab7/kernel/include/printf.h new file mode 100644 index 000000000..e58f666dc --- /dev/null +++ b/lab7/kernel/include/printf.h @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. +// Use this instead of bloated standard/newlib printf. +// These routines are thread safe and reentrant. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _PRINTF_H_ +#define _PRINTF_H_ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Output a character to a custom device like UART, used by the printf() function + * This function is declared here only. You have to write your custom implementation somewhere + * \param character Character to output + */ +void _putchar(char character); + + +/** + * Tiny printf implementation + * You have to implement _putchar if you use printf() + * To avoid conflicts with the regular printf() API it is overridden by macro defines + * and internal underscore-appended functions like printf_() are used + * \param format A string that specifies the format of the output + * \return The number of characters that are written into the array, not counting the terminating null character + */ +#define printf printf_ +int printf_(const char* format, ...); + + +/** + * Tiny sprintf implementation + * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD! + * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output! + * \param format A string that specifies the format of the output + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define sprintf sprintf_ +int sprintf_(char* buffer, const char* format, ...); + + +/** + * Tiny snprintf/vsnprintf implementation + * \param buffer A pointer to the buffer where to store the formatted string + * \param count The maximum number of characters to store in the buffer, including a terminating null character + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that COULD have been written into the buffer, not counting the terminating + * null character. A value equal or larger than count indicates truncation. Only when the returned value + * is non-negative and less than count, the string has been completely written. + */ +#define snprintf snprintf_ +#define vsnprintf vsnprintf_ +int snprintf_(char* buffer, size_t count, const char* format, ...); +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); + + +/** + * Tiny vprintf implementation + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define vprintf vprintf_ +int vprintf_(const char* format, va_list va); + + +/** + * printf with output function + * You may use this as dynamic alternative to printf() with its fixed _putchar() output + * \param out An output function which takes one character and an argument pointer + * \param arg An argument pointer for user data passed to output function + * \param format A string that specifies the format of the output + * \return The number of characters that are sent to the output function, not counting the terminating null character + */ +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); + + +#ifdef __cplusplus +} +#endif + + +#endif // _PRINTF_H_ \ No newline at end of file diff --git a/lab7/kernel/include/shell.h b/lab7/kernel/include/shell.h new file mode 100644 index 000000000..1f7075b10 --- /dev/null +++ b/lab7/kernel/include/shell.h @@ -0,0 +1,32 @@ +#include "uart.h" +#include "string.h" +#include "power.h" +#include "mbox.h" +#include "cpio.h" +#include "timer.h" +#include "exception.h" +#include "alloc.h" +#include "utils.h" +#include "thread.h" +#include "printf.h" +// #include "device_tree.h" +#define RAMFS_ADDR 0x8000000 + +void clean_buffer(char * buffer, int buffer_len); +void command_help(); +void command_hello(); +void command_not_found(char * buffer); +void command_ls(); +void command_cat(char* pathname); +void command_mailbox(); +void command_test(); +void command_load_user_program(const char *program_name); +void command_set_timeout(char *args); +void command_buddy_test(); +void command_dma_test(); +void command_thread_test1() ; +void command_thread_test2() ; +void command_thread_test3() ; +void command_thread_test4() ; +void parse_command(char * buffer); +void run_shell(); diff --git a/lab7/kernel/include/string.h b/lab7/kernel/include/string.h new file mode 100644 index 000000000..44b3b5416 --- /dev/null +++ b/lab7/kernel/include/string.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +int strcmp(const char *p1, const char *p2); +int strncmp(const char *s1, const char *s2, unsigned n); +int strlen(const char *s); +char *strstr(const char *s, const char *find); +char *strcpy(char *dst, const char *src); +char *strncpy(char *destination, const char *source, size_t len); +void strcat(char *to, const char *from); +char *strtok(char *s, const char delim); +char *split_last(char *str, char delim); \ No newline at end of file diff --git a/lab7/kernel/include/thread.h b/lab7/kernel/include/thread.h new file mode 100644 index 000000000..222838650 --- /dev/null +++ b/lab7/kernel/include/thread.h @@ -0,0 +1,88 @@ +#pragma once + +#include "utils.h" +#include "vfs.h" + +#define STACK_SIZE 4096 +#define USER_PROGRAM_BASE 0x30000000 +#define USER_PROGRAM_SIZE (1 * mb) + +#define THREAD_DEAD 1 +#define THREAD_FORK 2 +#define THREAD_READY 4 + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +#define FD_MAX 256 + +typedef struct { + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t fp; + uint64_t lr; + uint64_t sp; +} cpu_context; + +typedef struct { + struct file *files[FD_MAX]; +} fd_table_t; + +typedef struct thread_info { + cpu_context context; + uint32_t pid; + uint32_t child_pid; + int status; + uint64_t trap_frame_addr; + uint64_t kernel_stack_base; + uint64_t user_stack_base; + uint64_t user_program_base; + uint32_t user_program_size; + fd_table_t fd_table; + struct thread_info *next; +} thread_info; + +typedef struct { + thread_info *head, *tail; +} thread_queue; + +typedef struct { + uint64_t x[31]; +} trap_frame_t; + +thread_queue run_queue; +uint32_t thread_cnt; + +extern thread_info *get_current(); +extern void switch_to(thread_info *, thread_info *); + +void foo(); +void thread_test1(); +void thread_test2(); +void thread_test3(); +void thread_test4(); + +void thread_init(); +thread_info *thread_create(void (*func)()); +void schedule(); +void idle(); +void exit(); +void run_queue_push(thread_info *thread); +void kill_zombies(); +void exec(const char *program_name, const char **argv); +void fork(uint64_t sp); +void handle_fork(); +void create_child(thread_info *parent, thread_info *child); +void kill (int kill_pid); + +struct file *thread_get_file(int fd); +int thread_register_fd(struct file *file); +int thread_clear_fd(int fd); \ No newline at end of file diff --git a/lab7/kernel/include/timer.h b/lab7/kernel/include/timer.h new file mode 100644 index 000000000..e42bee18d --- /dev/null +++ b/lab7/kernel/include/timer.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#define CORE0_TIMER_IRQ_CTRL ((volatile unsigned int *)(0x40000040)) +#define CORE0_INTERRUPT_SOURCE ((volatile unsigned int *)(0x40000060)) + +typedef struct timeout_event { + uint32_t register_time; + uint32_t duration; + void (*callback)(char *); + char args[20]; + struct timeout_event *prev, *next; +} timeout_event; + +timeout_event *timeout_queue_head, *timeout_queue_tail; + +void timeout_event_init(); +void core_timer_enable(); +void core_timer_disable(); +void core_timer_handler_lowerEL_64(); +void core_timer_handler_currentEL_ELx(); +void add_timer(void (*callback)(char *), char *args, uint32_t duration); +uint64_t get_current_time(); +void set_expired_time(uint32_t duration); +void timer_callback(char *msg); \ No newline at end of file diff --git a/lab7/kernel/include/tmpfs.h b/lab7/kernel/include/tmpfs.h new file mode 100644 index 000000000..24f6539f8 --- /dev/null +++ b/lab7/kernel/include/tmpfs.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include "utils.h" +#include "vfs.h" + +#define MAX_FILES_IN_DIR 16 +#define TMPFS_BUF_SIZE (500 * kb) + +struct tmpfs_buf { + int flag; + size_t size; + char buffer[TMPFS_BUF_SIZE]; +}; + +struct tmpfs_fentry { + char name[20]; + FILE_TYPE type; + struct vnode* vnode; + struct vnode* parent_vnode; + struct tmpfs_fentry* child[MAX_FILES_IN_DIR]; + struct tmpfs_buf* buf; +}; + +struct vnode_operations* tmpfs_v_ops; +struct file_operations* tmpfs_f_ops; + +void tmpfs_init(); +void tmpfs_set_fentry(struct tmpfs_fentry* fentry, const char* component_name, + FILE_TYPE type, struct vnode* vnode); +int tmpfs_setup_mount(struct filesystem* fs, struct mount* mount); +int tmpfs_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name); +int tmpfs_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type); +int tmpfs_set_parent(struct vnode* child_node, struct vnode* parent_vnode); +int tmpfs_write(struct file* file, const void* buf, size_t len); +int tmpfs_read(struct file* file, void* buf, size_t len); +int tmpfs_list(struct file* file, void* buf, int index); \ No newline at end of file diff --git a/lab7/kernel/include/uart.h b/lab7/kernel/include/uart.h new file mode 100644 index 000000000..e81ea48cf --- /dev/null +++ b/lab7/kernel/include/uart.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#pragma once +#include "gpio.h" +#include "vfs.h" +#include + +#define ARM_IRQ_REG_BASE (MMIO_BASE + 0x0000b000) + +#define IRQ_PENDING_1 ((volatile unsigned int *)(ARM_IRQ_REG_BASE + 0x00000204)) +#define ENABLE_IRQS_1 ((volatile unsigned int *)(ARM_IRQ_REG_BASE + 0x00000210)) +#define DISABLE_IRQS_1 \ + ((volatile unsigned int *)(ARM_IRQ_REG_BASE + 0x0000021c)) + +#define AUX_IRQ (1 << 29) + +#define UART_BUFFER_SIZE 20 +char read_buf[UART_BUFFER_SIZE]; +char write_buf[UART_BUFFER_SIZE]; +int read_buf_start, read_buf_end; +int write_buf_start, write_buf_end; + +void uart_init(); +void uart_send(unsigned int c); +char uart_getc(); +uint32_t uart_gets(char *buf, uint32_t size); +void uart_puts(char *s); +void uart_hex(unsigned int d); +void uart_putc(char c); +void uart_int(int x); +uint32_t uart_write(char *s, uint32_t size); + +void enable_uart_interrupt(); +void disable_uart_interrupt(); +void assert_transmit_interrupt(); +void clear_transmit_interrupt(); +void uart_handler(); +char uart_async_getc(); +void uart_async_puts(char *str); \ No newline at end of file diff --git a/lab7/kernel/include/utils.h b/lab7/kernel/include/utils.h new file mode 100644 index 000000000..085a90b13 --- /dev/null +++ b/lab7/kernel/include/utils.h @@ -0,0 +1,15 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ +#include +uint64_t hex_to_int64(char* num); +uint8_t hex_to_int8(char hex); +uint64_t hex2int(char *hex, int len); +uint64_t align_up(uint64_t addr, uint64_t alignment); +uint64_t align_up_exp(uint64_t n); +#define kb ((uint64_t)0x400) +#define mb ((uint64_t)0x100000) +#define gb ((uint64_t)0x40000000) +uint64_t log2(uint64_t num); +void delay(int num); +uint32_t be2le(uint32_t x); +#endif diff --git a/lab7/kernel/include/vfs.h b/lab7/kernel/include/vfs.h new file mode 100644 index 000000000..08c3321a1 --- /dev/null +++ b/lab7/kernel/include/vfs.h @@ -0,0 +1,81 @@ +#pragma once + +#include + +#define O_CREAT 00000100 + +typedef enum { FILE_DIRECTORY, FILE_REGULAR, FILE_DEVICE, FILE_NONE } FILE_TYPE; +typedef enum { STDIN, STDOUT, STDERR } FILENO; + +struct vnode { + struct mount* mount; + struct vnode_operations* v_ops; + struct file_operations* f_ops; + void* internal; +}; + +struct file { + struct vnode* vnode; + size_t f_pos; // The next read/write position of this opened file + struct file_operations* f_ops; + int flags; +}; + +struct mount { + struct vnode* root; + struct filesystem* fs; + char mount_entry[20]; +}; + +struct filesystem { + const char* name; + int (*setup_mount)(struct filesystem* fs, struct mount* mount); + struct filesystem* next; +}; + +struct filesystem_list { + struct filesystem *head, *tail; +}; + +struct file_operations { + int (*write)(struct file* file, const void* buf, size_t len); + int (*read)(struct file* file, void* buf, size_t len); + int (*list)(struct file* file, void* buf, int index); +}; + +struct vnode_operations { + int (*lookup)(struct vnode* dir_node, struct vnode** target, + const char* component_name); + int (*create)(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type); + int (*set_parent)(struct vnode* child_node, struct vnode* parent_node); +}; + +// file system +struct file * stdin; +struct file * stdout; +struct file * stderr; + +struct filesystem_list fs_list; +struct mount* rootfs; +struct vnode* current_dir; + +void vfs_test(); +void vfs_ls_test(); +void vfs_hard_test(); +void vfs_fat_test(); + +void vfs_init(); +int register_filesystem(struct filesystem* fs); +struct filesystem* get_fs_by_name(const char* name); +int vfs_find_vnode(struct vnode** target, const char* pathname); +struct file* vfs_open(const char* pathname, int flags); +int vfs_close(struct file* file); +int vfs_write(struct file* file, const void* buf, size_t len); +int vfs_read(struct file* file, void* buf, size_t len); +int vfs_list(struct file* file, void* buf, int index); +int vfs_mkdir(const char* pathname); +int vfs_chdir(const char* pathname); +int vfs_mount(const char* device, const char* mountpoint, + const char* filesystem); +int vfs_umount(const char* mountpoint); \ No newline at end of file diff --git a/lab7/kernel/initramfs/argv_test b/lab7/kernel/initramfs/argv_test new file mode 100755 index 000000000..bab6dec40 Binary files /dev/null and b/lab7/kernel/initramfs/argv_test differ diff --git a/lab7/kernel/initramfs/fork_test b/lab7/kernel/initramfs/fork_test new file mode 100755 index 000000000..77f02bab8 Binary files /dev/null and b/lab7/kernel/initramfs/fork_test differ diff --git a/lab7/kernel/initramfs/my_test b/lab7/kernel/initramfs/my_test new file mode 100755 index 000000000..347d3283c Binary files /dev/null and b/lab7/kernel/initramfs/my_test differ diff --git a/lab7/kernel/initramfs/my_test2 b/lab7/kernel/initramfs/my_test2 new file mode 100755 index 000000000..18d7dbebb Binary files /dev/null and b/lab7/kernel/initramfs/my_test2 differ diff --git a/lab7/kernel/initramfs/svc_test b/lab7/kernel/initramfs/svc_test new file mode 100755 index 000000000..1b407b1fa Binary files /dev/null and b/lab7/kernel/initramfs/svc_test differ diff --git a/lab7/kernel/initramfs/vfs1.img b/lab7/kernel/initramfs/vfs1.img new file mode 100644 index 000000000..2c41bd71a Binary files /dev/null and b/lab7/kernel/initramfs/vfs1.img differ diff --git a/lab7/kernel/src/alloc.c b/lab7/kernel/src/alloc.c new file mode 100644 index 000000000..a4d026a16 --- /dev/null +++ b/lab7/kernel/src/alloc.c @@ -0,0 +1,446 @@ +#include "alloc.h" +#include "uart.h" +#include "utils.h" +#include "printf.h" + +void buddy_test() { + print_frame_lists(); + uint64_t size[6] = { + PAGE_SIZE * 1, PAGE_SIZE * 13, PAGE_SIZE * 16, + PAGE_SIZE * 2, PAGE_SIZE * 4, PAGE_SIZE * 8, + }; + page_frame *frame_ptr[6]; + printf("********** buddy allocation test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + frame_ptr[i] = buddy_allocate(size[i]); + printf("Successfully allocate %lld pages\n", size[i] / PAGE_SIZE); + // if (c == 'p') + print_frame_lists(); + } + print_frame_lists(); + printf("********** buddy free test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + buddy_free(frame_ptr[i]); + printf("Successfully free %lld pages\n", size[i] / PAGE_SIZE); + // if (c == 'p') + print_frame_lists(); + } +} + +void dma_test() { + print_frame_lists(); + print_dma_list(); + // int *ptr1 = malloc(sizeof(int)); + // int *ptr2 = malloc(sizeof(int) * 1024); + // int *ptr3 = malloc(sizeof(int)); + // print_dma_list(); + // free(ptr1); + // print_dma_list(); + // free(ptr2); + // print_dma_list(); + // free(ptr3); + + uint64_t size[6] = { + sizeof(int) * 1, sizeof(int) * 8, sizeof(int) * 2201, + sizeof(int) * 9, sizeof(int) * 3068, sizeof(int) * 100, + }; + void *ptr[6]; + + printf("********** malloc test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + ptr[i] = malloc(size[i]); + printf("Successfully allocate %lld bytes in address %p\n", size[i], ptr[i]); + // if (c == 'p') { + print_frame_lists(); + print_dma_list(); // printf( + // "put frame index %d back to free lists (4K x 2^%lld = %lld KB)\n", + // id, frames[id].order, 1 << (frames[id].order + 2)); + // } + } + // print_frame_lists(); + // print_dma_list(); + printf("********** free test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + free(ptr[i]); + printf("Successfully free %lld bytes in address %p\n", size[i], ptr[i]); + // if (c == 'p') { + print_frame_lists(); + print_dma_list(); + // } + } +} + +void buddy_init() { + for (int i = 0; i < MAX_PAGE_NUM; i++) { + frames[i].id = i; + frames[i].order = -1; + frames[i].is_allocated = 0; + frames[i].addr = PAGE_BASE_ADDR + i * PAGE_SIZE; + frames[i].next = 0; + } + for (int i = 0; i < FRAME_LIST_NUM; i++) { + free_frame_lists[i] = 0; + used_frame_lists[i] = 0; + } + frames[0].order = MAX_FRAME_ORDER; + free_frame_lists[MAX_FRAME_ORDER] = &frames[0]; + free_dma_list = 0; +} + +page_frame * buddy_allocate(uint64_t size) { + // printf("Enter size (kb): "); + // int kb_size = read_i(); + uint64_t page_num = size / PAGE_SIZE; + if (size % PAGE_SIZE != 0) page_num++; + page_num = align_up_exp(page_num); + uint64_t order = log2(page_num); + + for (uint64_t i = order; i <= MAX_FRAME_ORDER; i++) { + // printf("i = "); + // uart_int(i); + // printf("\n"); + + if (free_frame_lists[i]) { + int cur_id = free_frame_lists[i]->id; + free_frame_lists[i] = free_frame_lists[i]->next; + frames[cur_id].order = order; + frames[cur_id].is_allocated = 1; + frames[cur_id].next = used_frame_lists[order]; + used_frame_lists[order] = &frames[cur_id]; + // printf("allocate frame index %d (4K x 2^%lld = %lld KB)\n", cur_id, order, + // 1 << (order + 2)); + + // release redundant memory block + for (; i > order; i--) { + int id = cur_id + (1 << (i - 1)); + frames[id].order = i - 1; + frames[id].is_allocated = 0; + frames[id].next = free_frame_lists[i - 1]; + free_frame_lists[i - 1] = &frames[id]; + // printf( + // "put frame index %d back to free lists (4K x 2^%lld = %lld KB)\n", + // id, frames[id].order, 1 << (frames[id].order + 2)); + } + // printf("\n"); + // print_frame_lists(); + return &frames[cur_id]; + } + } + return 0; +} + +void buddy_free(page_frame *frame) { + // printf("Enter address (hex): "); + // uint64_t addr = read_h(); + uint64_t index = frame->id; + if (!frames[index].is_allocated) { + printf("Error: it is already free\n"); + return; + } + uint64_t order = frames[index].order; + // printf("index :"); + // uart_int(index); + // printf("order :"); + // uart_int(order); + // printf("\n"); + buddy_unlink(index, 1); + // iterative merge + while (order <= MAX_FRAME_ORDER) { + uint64_t target_index = index ^ (1 << order); // XOR to find same size page + // printf("target_index :"); + // uart_int(target_index); + // printf("\n"); + if ((target_index >= MAX_PAGE_NUM) || frames[target_index].is_allocated || + (frames[target_index].order != order)) + break; + + // printf("merge with frame index %d (4K x 2^%lld = %lld KB)\n", target_index, + // frames[target_index].order, 1 << (frames[target_index].order + 2)); + order += 1; + // iterative part + if (index > target_index) index = target_index; + } + frames[index].order = order; + frames[index].next = free_frame_lists[order]; + free_frame_lists[order] = &frames[index]; + // printf("put frame index %d back (4K x 2^%lld = %lld KB)\n", index, + // frames[index].order, 1 << (frames[index].order + 2)); + // print_frame_lists(); +} + +void buddy_unlink(int index, int type) { + uint64_t order = frames[index].order; + frames[index].order = -1; + frames[index].is_allocated = 0; + + if (type == 0) { + if (free_frame_lists[order] == &frames[index]) { + free_frame_lists[order] = frames[index].next; + frames[index].next = 0; + } else { + // printf("=========linked list search free=======\n"); + for (page_frame *cur = free_frame_lists[order]; cur; cur = cur->next) { + if (cur->next == &frames[index]) { + cur->next = frames[index].next; + frames[index].next = 0; + break; + } + } + } + } + if (type == 1) { + if (used_frame_lists[order] == &frames[index]) { + used_frame_lists[order] = frames[index].next; + frames[index].next = 0; + } else { + // printf("=========linked list search used=======\n"); + for (page_frame *cur = used_frame_lists[order]; cur; cur = cur->next) { + if (cur->next == &frames[index]) { + cur->next = frames[index].next; + frames[index].next = 0; + break; + } + } + } + } +} + +void print_frame_lists() { + printf("========================\n"); + printf("Free frame lists: \n"); + for (int i = MAX_FRAME_ORDER; i >= 0; i--) { + printf("4K x 2^%d (%d KB):", i, 1 << (i + 2)); + for (page_frame *cur = free_frame_lists[i]; cur; cur = cur->next) { + printf(" index %d(0x%x)", cur->id, cur->addr); + } + printf("\n"); + } + printf("\n"); + printf("Used frame lists: \n"); + for (int i = MAX_FRAME_ORDER; i >= 0; i--) { + printf("4K x 2^%d (%d KB):", i, 1 << (i + 2)); + for (page_frame *cur = used_frame_lists[i]; cur; cur = cur->next) { + printf(" index %d(0x%x)", cur->id, cur->addr); + } + printf("\n"); + } + printf("========================\n"); +} + +void *malloc(uint64_t size) { + dma_header *free_slot = 0; + uint64_t min_size = ((uint64_t)1) << 63; + // printf("min_size :"); + // uart_int(min_size); + // printf("\n"); + // printf("size :"); + // uart_int(size); + // printf("\n"); + // find the smallest free slot which is bigger than the required size + for (dma_header *cur = free_dma_list; cur; cur = cur->next) { + // printf("find the smallest free slot which is bigger than the required size\n"); + + uint64_t data_size = cur->total_size - align_up(sizeof(dma_header), 8); + if (data_size >= align_up(size, 8) && data_size < min_size) { + free_slot = cur; + min_size = data_size; + } + } + + uint64_t allocated_size = align_up(sizeof(dma_header), 8) + align_up(size, 8); + // printf("allocated_size :"); + // uart_int(allocated_size); + // printf("\n"); + if (free_slot) { + // printf("have free_slot\n"); + + uint64_t addr = (uint64_t)free_slot; + uint64_t total_size = free_slot->total_size; + // rewrite the found free slot + free_slot->total_size = allocated_size; + free_slot->used_size = size; + free_slot->is_allocated = 1; + if (free_slot->prev) { + // printf("if (free_slot->prev)\n"); + free_slot->prev->next = free_slot->next; + } + if (free_slot->next) { + // printf("if (free_slot->next)\n"); + free_slot->next->prev = free_slot->prev; + } + if (free_dma_list == free_slot){ + // printf("if (free_slot->prev)\n"); + free_dma_list = free_slot->next; + } + free_slot->prev = 0; + free_slot->next = 0; + + // create another free slot if remaining size is big enough + int64_t free_size = + total_size - allocated_size - align_up(sizeof(dma_header), 8); + if (free_size > 0) { + dma_header *new_header = (dma_header *)(addr + allocated_size); + new_header->total_size = total_size - allocated_size; + new_header->used_size = 0; + new_header->is_allocated = 0; + new_header->frame_ptr = free_slot->frame_ptr; + new_header->prev = 0; + new_header->next = free_dma_list; + if (free_dma_list) free_dma_list->prev = new_header; + free_dma_list = new_header; + } else { + free_slot->total_size = total_size; + } + return (void *)(addr + align_up(sizeof(dma_header), 8)); + } else { + // printf("no free_slot\n"); + + // allocate a page + page_frame *frame_ptr = buddy_allocate(allocated_size); + uint64_t addr = frame_ptr->addr; + // printf("addr :"); + // uart_hex(addr); + // printf("\n"); + // create a free slot + dma_header *allocated_header = (dma_header *)addr; + allocated_header->total_size = allocated_size; + allocated_header->used_size = size; + allocated_header->is_allocated = 1; + allocated_header->frame_ptr = frame_ptr; + allocated_header->prev = 0; + allocated_header->next = 0; + // create another free slot if remaining size is big enough + uint64_t order = frame_ptr->order; + uint64_t total_size = (1 << order) * 4 * kb; + int64_t free_size = total_size - allocated_size - align_up(sizeof(dma_header), 8); + // printf("order :"); + // uart_int(order); + // printf("\n"); + // printf("total_size :"); + // uart_int(total_size); + // printf("\n"); + // printf("free_size :"); + // uart_int(free_size); + // printf("\n"); + if (free_size > 0) { + dma_header *new_header = (dma_header *)(addr + allocated_size); + new_header->total_size = total_size - allocated_size; + new_header->used_size = 0; + new_header->is_allocated = 0; + new_header->frame_ptr = frame_ptr; + new_header->prev = 0; + new_header->next = free_dma_list; + if (free_dma_list) free_dma_list->prev = new_header; + free_dma_list = new_header; + } else { + allocated_header->total_size = total_size; + } + return (void *)(addr + align_up(sizeof(dma_header), 8)); + } + return 0; +} + +void free(void *ptr) { + uint64_t target_addr = (uint64_t)ptr - align_up(sizeof(dma_header), 8); + dma_header *target_header = (dma_header *)target_addr; + target_header->used_size = 0; + target_header->is_allocated = 0; + target_header->prev = 0; + target_header->next = free_dma_list; + if (free_dma_list) free_dma_list->prev = target_header; + free_dma_list = target_header; + + // uart_hex((uint64_t)ptr); + // printf("\n"); + // uart_hex(target_addr); + // printf("\n"); + + page_frame *frame_ptr = target_header->frame_ptr; + uint64_t base_addr = frame_ptr->addr; + uint64_t order = frame_ptr->order; + uint64_t total_frame_size = (1 << order) * 4 * kb; + uint64_t boundary = base_addr + total_frame_size; + + // uart_hex(base_addr); + // printf("\n"); + // uart_hex(total_size); + // printf("\n"); + + // merge next slot if it is free + uint64_t next_addr = target_addr + target_header->total_size; + dma_header *next_header = (dma_header *)next_addr; + if (next_addr < boundary && !next_header->is_allocated) { + if (next_header->prev) next_header->prev->next = next_header->next; + if (next_header->next) next_header->next->prev = next_header->prev; + if (free_dma_list == next_header) free_dma_list = next_header->next; + next_header->prev = 0; + next_header->next = 0; + target_header->total_size += next_header->total_size; + } + // uart_int(target_header->total_size); + // printf("\n"); + // print_dma_list(); + + // merge previous slot if it is free + uint64_t current_addr = base_addr; + while (current_addr < boundary) { + dma_header *header = (dma_header *)current_addr; + uint64_t next_addr = current_addr + header->total_size; + // uart_hex(current_addr); + // printf("\n"); + // uart_hex(next_addr); + // printf("\n"); + if (next_addr == target_addr) { + if (!header->is_allocated) { + header->total_size += target_header->total_size; + // uart_int(header->total_size); + // printf("\n"); + if (target_header->prev) + target_header->prev->next = target_header->next; + if (target_header->next) + target_header->next->prev = target_header->prev; + if (free_dma_list == target_header) free_dma_list = target_header->next; + target_header->prev = 0; + target_header->next = 0; + } + break; + } + current_addr = next_addr; + } + + // free page frame if all slots are free + dma_header *base_header = (dma_header *)base_addr; + if (base_header->total_size == total_frame_size) { + if (base_header->prev) base_header->prev->next = base_header->next; + if (base_header->next) base_header->next->prev = base_header->prev; + if (free_dma_list == base_header) free_dma_list = base_header->next; + base_header->prev = 0; + base_header->next = 0; + buddy_free(frame_ptr); + } +} + +void print_dma_list() { + printf("========================\n"); + printf("Free DMA slots: \n"); + for (dma_header *cur = free_dma_list; cur; cur = cur->next) { + printf("size: "); + uart_int(cur->total_size - align_up(sizeof(dma_header), 8)); + printf(", frame index: "); + uart_int(cur->frame_ptr->id); + printf("\n"); + } + printf("========================\n"); +} diff --git a/lab7/kernel/src/cpio.c b/lab7/kernel/src/cpio.c new file mode 100644 index 000000000..20badd688 --- /dev/null +++ b/lab7/kernel/src/cpio.c @@ -0,0 +1,273 @@ +#include "cpio.h" +#include "printf.h" +#include "string.h" +#include "utils.h" +#include "vfs.h" +#include "alloc.h" + +void cpio_ls() { + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + printf("%s ", pathname); + + ptr = align_up(ptr + namesize, 4); + ptr = align_up(ptr + filesize, 4); + } + printf("\n"); +} + +void cpio_cat(char *pathname_to_cat) { + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + + ptr = align_up(ptr + namesize, 4); + if (strcmp(pathname, pathname_to_cat) == 0) { + char *content = (char *)ptr; + for (unsigned long long i = 0; i < filesize; i++) { + printf("%c", content[i]); + } + printf("\n"); + return; + } + ptr = align_up(ptr + filesize, 4); + } + printf("No such file\n"); +} + +uint32_t cpio_load_user_program(const char *target_program, + uint64_t target_addr) { + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + + ptr = align_up(ptr + namesize, 4); + if (strcmp(pathname, target_program) == 0) { + char *content = (char *)ptr; + char *target_content = (char *)target_addr; + for (unsigned long long i = 0; i < filesize; i++) { + target_content[i] = content[i]; + } + return filesize; + } + ptr = align_up(ptr + filesize, 4); + } + printf("No such file\n"); + return 0; +} + +void cpio_populate_rootfs() { + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + printf("%s %d\n", pathname, filesize); + + ptr = align_up(ptr + namesize, 4); + struct file* file = vfs_open(pathname, O_CREAT); + if (file) { + vfs_write(file, (const char *)ptr, filesize); + vfs_close(file); + } + ptr = align_up(ptr + filesize, 4); + } +} + +// cpiofs +void cpiofs_init() { + cpiofs_v_ops = + (struct vnode_operations*)malloc(sizeof(struct vnode_operations)); + cpiofs_v_ops->lookup = cpiofs_lookup; + cpiofs_v_ops->create = cpiofs_create; + cpiofs_v_ops->set_parent = cpiofs_set_parent; + cpiofs_f_ops = (struct file_operations*)malloc(sizeof(struct file_operations)); + cpiofs_f_ops->write = cpiofs_write; + cpiofs_f_ops->read = cpiofs_read; + cpiofs_f_ops->list = cpiofs_list; +} + +int _cpiofs_create(struct vnode* dir_node, struct cpiofs_file* file, + const char* component_name, FILE_TYPE type) { + + for (int i = 0; i < MAX_FILES_IN_DIR; i++) { + struct cpiofs_fentry* fentry = + ((struct cpiofs_fentry*)dir_node->internal)->child[i]; + if (fentry->type == FILE_NONE) { + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = 0; + vnode->v_ops = dir_node->v_ops; + vnode->f_ops = dir_node->f_ops; + vnode->internal = fentry; + cpiofs_set_fentry(fentry, component_name, file, type, vnode); + // *target = fentry -> vnode; + return 1; + } + } + return -1; +} + +void cpiofs_set_fentry(struct cpiofs_fentry* fentry, const char* component_name, + struct cpiofs_file* file, FILE_TYPE type, struct vnode* vnode) { + strcpy(fentry->name, component_name); + fentry->vnode = vnode; + fentry->type = type; + fentry->file = file; + + if (fentry->type == FILE_DIRECTORY) { + for (int i = 0; i < MAX_FILES_IN_DIR; ++i) { + fentry->child[i] = + (struct cpiofs_fentry*)malloc(sizeof(struct cpiofs_fentry)); + fentry->child[i]->name[0] = 0; + fentry->child[i]->type = FILE_NONE; + fentry->child[i]->parent_vnode = vnode; + } + fentry->file->size = CPIOFS_BUF_SIZE; + } +} + +int cpiofs_setup_mount(struct filesystem* fs, struct mount* mount) { + struct cpiofs_fentry* root_fentry = + (struct cpiofs_fentry*)malloc(sizeof(struct cpiofs_fentry)); + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = mount; + vnode->v_ops = cpiofs_v_ops; + vnode->f_ops = cpiofs_f_ops; + vnode->internal = (void*)root_fentry; + root_fentry->parent_vnode = 0; + cpiofs_set_fentry(root_fentry, "/", 0 , FILE_DIRECTORY, vnode); + mount->fs = fs; + mount->root = vnode; + + // scan cpio + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + // printf("%s %d\n", pathname, filesize); + + ptr = align_up(ptr + namesize, 4); + + struct cpiofs_file* file = (struct cpiofs_file*)malloc(sizeof(struct cpiofs_file)); + file->buffer = (char *)ptr; + file->size = filesize; + _cpiofs_create(mount->root , file, pathname, FILE_REGULAR); + + ptr = align_up(ptr + filesize, 4); + } + return 1; +} + +int cpiofs_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name) { + // printf("[lookup] %s\n", component_name); + struct cpiofs_fentry* fentry = (struct cpiofs_fentry*)dir_node->internal; + if (fentry->type != FILE_DIRECTORY) return 0; + + if (!strcmp(component_name, ".")) { + *target = fentry->vnode; + return 1; + } + if (!strcmp(component_name, "..")) { + if (!fentry->parent_vnode) return 0; + *target = fentry->parent_vnode; + return 1; + } + + for (int i = 0; i < MAX_FILES_IN_DIR; i++) { + fentry = ((struct cpiofs_fentry*)dir_node->internal)->child[i]; + if (!strcmp(fentry->name, component_name)) { + *target = fentry->vnode; + return 1; + } + } + return 0; +} + +int cpiofs_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type) { + printf("[ERROR] Can't create, R_ONLY\n"); + return -1; +} + +int cpiofs_set_parent(struct vnode* child_node, struct vnode* parent_vnode) { + struct cpiofs_fentry* fentry = (struct cpiofs_fentry*)child_node->internal; + fentry->parent_vnode = parent_vnode; + return 1; +} + +int cpiofs_write(struct file* file, const void* buf, size_t len) { + printf("[ERROR] Can't write, R_ONLY\n"); + return -1; +} + +int cpiofs_read(struct file* file, void* buf, size_t len) { + size_t read_len = 0; + struct cpiofs_fentry* fentry = (struct cpiofs_fentry*)file->vnode->internal; + for (size_t i = 0; i < len; i++) { + ((char*)buf)[i] = fentry->file->buffer[file->f_pos++]; + read_len++; + if (read_len == fentry->file->size) { + break; + } + } + return read_len; +} + +int cpiofs_list(struct file* file, void* buf, int index) { + struct cpiofs_fentry* fentry = (struct cpiofs_fentry*)file->vnode->internal; + if (fentry->type != FILE_DIRECTORY) return -1; + if (index >= MAX_FILES_IN_DIR) return -1; + + if (fentry->child[index]->type == FILE_NONE) return 0; + strcpy((char*)buf, fentry->child[index]->name); + return fentry->child[index]->file->size; +} \ No newline at end of file diff --git a/lab7/kernel/src/delays.c b/lab7/kernel/src/delays.c new file mode 100644 index 000000000..aba77264d --- /dev/null +++ b/lab7/kernel/src/delays.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" + +#define SYSTMR_LO ((volatile unsigned int*)(MMIO_BASE+0x00003004)) +#define SYSTMR_HI ((volatile unsigned int*)(MMIO_BASE+0x00003008)) + +/** + * Wait N CPU cycles (ARM CPU only) + */ +void wait_cycles(unsigned int n) +{ + if(n) while(n--) { asm volatile("nop"); } +} + +/** + * Wait N microsec (ARM CPU only) + */ +void wait_msec(unsigned int n) +{ + register unsigned long f, t, r; + // get the current counter frequency + asm volatile ("mrs %0, cntfrq_el0" : "=r"(f)); + // read the current counter + asm volatile ("mrs %0, cntpct_el0" : "=r"(t)); + // calculate expire value for counter + t+=((f/1000)*n)/1000; + do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(rlookup = device_lookup; + device_v_ops->create = device_create; + device_v_ops->set_parent = device_set_parent; + device_f_ops = (struct file_operations*)malloc(sizeof(struct file_operations)); + device_f_ops->write = device_write; + device_f_ops->read = device_read; + // device_f_ops->list = device_list; +} + +void uartfs_init() { + uartfs_v_ops = + (struct vnode_operations*)malloc(sizeof(struct vnode_operations)); + uartfs_v_ops->lookup = device_lookup; + uartfs_v_ops->create = device_create; + uartfs_v_ops->set_parent = device_set_parent; + uartfs_f_ops = (struct file_operations*)malloc(sizeof(struct file_operations)); + uartfs_f_ops->write = uartfs_write; + uartfs_f_ops->read = uartfs_read; + // uartfs_f_ops->list = device_list; +} + +void fb_init() { + fb_v_ops = + (struct vnode_operations*)malloc(sizeof(struct vnode_operations)); + fb_v_ops->lookup = device_lookup; + fb_v_ops->create = device_create; + fb_v_ops->set_parent = device_set_parent; + fb_f_ops = (struct file_operations*)malloc(sizeof(struct file_operations)); + fb_f_ops->write = fb_write; + // fb_f_ops->read = fb_read; + // uartfs_f_ops->list = device_list; +} + +void device_init() { + root_init(); + uartfs_init(); + fb_init(); +} + +void device_set_fentry(struct device_fentry* fentry, const char* component_name, + struct vnode* vnode, DEV_TYPE type) { + // printf("[device_set_fentry]\n"); + strcpy(fentry->name, component_name); + fentry->vnode = vnode; + fentry->type = type; + + if (fentry->type == DEV_ROOT) { + for (int i = 0; i < MAX_DEVICE_IN_DIR; ++i) { + fentry->child[i] = + (struct device_fentry*)malloc(sizeof(struct device_fentry)); + fentry->child[i]->name[0] = 0; + fentry->child[i]->type = DEV_NONE; + fentry->child[i]->parent_vnode = vnode; + } + } +} + +int device_setup_mount(struct filesystem* fs, struct mount* mount) { + // setup cpio root node + struct device_fentry* root_fentry = + (struct device_fentry*)malloc(sizeof(struct device_fentry)); + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode));; + vnode->mount = mount; + vnode->v_ops = device_v_ops; + vnode->f_ops = device_f_ops; + vnode->internal = (void*)root_fentry; + root_fentry->parent_vnode = 0; + device_set_fentry(root_fentry, "/", vnode, DEV_ROOT); + mount->fs = fs; + mount->root = vnode; + + // create device vnode + _device_create(mount->root, "uart", DEV_UART); + // create frame buffer + _device_create(mount->root, "framebuffer", DEV_FB); + + return 1; +} + +int device_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name) { + + // printf("[device_lookup] %s\n", component_name); + struct device_fentry* fentry = (struct device_fentry*)dir_node->internal; + if (fentry->type != DEV_ROOT) return 0; + + if (!strcmp(component_name, ".")) { + //printf("[device_lookup] .\n"); + *target = fentry->vnode; + return 1; + } + if (!strcmp(component_name, "..")) { + //printf("[device_lookup] ..\n"); + if (!fentry->parent_vnode) return 0; + *target = fentry->parent_vnode; + return 1; + } + + for (int i = 0; i < MAX_DEVICE_IN_DIR; i++) { + fentry = ((struct device_fentry*)dir_node->internal)->child[i]; + // printf("[device_lookup] %s\n", fentry->name); + if (!strcmp(fentry->name, component_name)) { + *target = fentry->vnode; + return 1; + } + } + return 0; +} + +int _device_create(struct vnode* dir_node, + const char* component_name, DEV_TYPE type) { + + for (int i = 0; i < MAX_DEVICE_IN_DIR; i++) { + struct device_fentry* fentry = + ((struct device_fentry*)dir_node->internal)->child[i]; + if (fentry->type == DEV_NONE) { + + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = 0; + if(type == DEV_UART){ + vnode->v_ops = uartfs_v_ops; + vnode->f_ops = uartfs_f_ops; + vnode->internal = fentry; + device_set_fentry(fentry, component_name, vnode, type); + return 1; + } + else if(type == DEV_FB){ + vnode->v_ops = fb_v_ops; + vnode->f_ops = fb_f_ops; + vnode->internal = fentry; + device_set_fentry(fentry, component_name, vnode, type); + return 1; + } + } + } + return -1; +} + +void device_list(struct vnode* dir_node) { + printf("[device_list]: listing dir: %s\n", ((struct device_fentry*)dir_node->internal)->name); + for (int i = 0; i < MAX_DEVICE_IN_DIR; i++) { + struct device_fentry* fentry = + ((struct device_fentry*)dir_node->internal)->child[i]; + if (fentry->type != DEV_NONE) { + printf("[type]: %d, [name]: %s\n", fentry->type, fentry->name); + } + } + printf("\n"); +} + +int device_set_parent(struct vnode* child_node, struct vnode* parent_vnode) { + struct device_fentry* fentry = (struct device_fentry*)child_node->internal; + fentry->parent_vnode = parent_vnode; + return 1; +} + +int device_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type) { + printf("[device_create] no create function for /dev\n"); + return -1; +} + +int device_write(struct file* file, const void* buf, size_t len) { + /* todo */ + printf("[device_write] no write function for /dev\n"); + return -1; +} + +int device_read(struct file* file, void* buf, size_t len) { + printf("[device_read] no read function for /dev\n"); + return -1; +} + +// uart read write functions + +int uartfs_read(struct file* file, void* buf, size_t len) { + size_t read_len = 0; + struct device_fentry* fentry = (struct device_fentry*)file->vnode->internal; + for (size_t i = 0; i < len; i++) { + if(fentry->type == DEV_UART){ + ((char*)buf)[i] = uart_getc(); + } + read_len++; + } + return read_len; +} + +int uartfs_write(struct file* file, const void* buf, size_t len) { + for (size_t i = 0; i < len; i++) { + uart_send( ((char*)buf)[i] ); + } + return len; +} + +int fb_write(struct file* file, const void* buf, size_t len) { + // printf("[fb_write]\n"); + // write to lfb + // printf("file->f_pos = %d\n",file->f_pos); + // for(int i = 0; i < len; i++) printf("0x%x, ", ((char* )buf)[i]); + // printf("\n"); + if(isrgb){ //RGB + lfb[file->f_pos++] = ((char* )buf)[0]; + lfb[file->f_pos++] = ((char* )buf)[1]; + lfb[file->f_pos++] = ((char* )buf)[2]; + + lfb[file->f_pos++] = ((char* )buf)[3]; + } + else{ //BGR + lfb[file->f_pos++] = ((char* )buf)[2]; + lfb[file->f_pos++] = ((char* )buf)[1]; + lfb[file->f_pos++] = ((char* )buf)[0]; + + lfb[file->f_pos++] = ((char* )buf)[3]; // 0x0 + } + + return len; +} + +long lseek64(int fd, long offset, int whence){ + struct file* file = thread_get_file(fd); + file->f_pos = offset + whence; + return file->f_pos; +} + +int ioctl(int fd, unsigned long request, struct framebuffer_info * info){ + #define MBOX_REQUEST 0 + #define MBOX_CH_PROP 8 + #define MBOX_TAG_LAST 0 + unsigned int __attribute__((aligned(16))) mbox[36]; + unsigned int width, height, pitch; /* dimensions and channel order */ + + mbox[0] = 35 * 4; + mbox[1] = MBOX_REQUEST; + + mbox[2] = 0x48003; // set phy wh + mbox[3] = 8; + mbox[4] = 8; + mbox[5] = 1024; // FrameBufferInfo.width + mbox[6] = 768; // FrameBufferInfo.height + + mbox[7] = 0x48004; // set virt wh + mbox[8] = 8; + mbox[9] = 8; + mbox[10] = 1024; // FrameBufferInfo.virtual_width + mbox[11] = 768; // FrameBufferInfo.virtual_height + + mbox[12] = 0x48009; // set virt offset + mbox[13] = 8; + mbox[14] = 8; + mbox[15] = 0; // FrameBufferInfo.x_offset + mbox[16] = 0; // FrameBufferInfo.y.offset + + mbox[17] = 0x48005; // set depth + mbox[18] = 4; + mbox[19] = 4; + mbox[20] = 32; // FrameBufferInfo.depth + + mbox[21] = 0x48006; // set pixel order + mbox[22] = 4; + mbox[23] = 4; + mbox[24] = 1; // RGB, not BGR preferably + + mbox[25] = 0x40001; // get framebuffer, gets alignment on request + mbox[26] = 8; + mbox[27] = 8; + mbox[28] = 4096; // FrameBufferInfo.pointer + mbox[29] = 0; // FrameBufferInfo.size + + mbox[30] = 0x40008; // get pitch + mbox[31] = 4; + mbox[32] = 4; + mbox[33] = 0; // FrameBufferInfo.pitch + + mbox[34] = MBOX_TAG_LAST; + + // this might not return exactly what we asked for, could be + // the closest supported resolution instead + if (mbox_call(MBOX_CH_PROP, mbox) && mbox[20] == 32 && mbox[28] != 0) { + mbox[28] &= 0x3FFFFFFF; // convert GPU address to ARM address + width = mbox[5]; // get actual physical width + height = mbox[6]; // get actual physical height + pitch = mbox[33]; // get number of bytes per line + isrgb = mbox[24]; // get the actual channel order + lfb = (void *)((unsigned long)mbox[28]); + printf("width =%d, height =%d, pitch =%d, isrgb =%d\n", width, height, pitch, isrgb); + } else { + printf("Unable to set screen resolution to 1024x768x32\n"); + } + return 1; +} diff --git a/lab7/kernel/src/dtb.c b/lab7/kernel/src/dtb.c new file mode 100644 index 000000000..e9461b191 --- /dev/null +++ b/lab7/kernel/src/dtb.c @@ -0,0 +1,252 @@ +#include "dtb.h" + +#include "printf.h" +#include "string.h" +#include "utils.h" + +void mailbox_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + if (check_compatibility(struct_addr, strings_addr, "brcm,bcm2835-mbox") == 0) + return; + print_node(struct_addr, strings_addr, depth); +} + +void gpio_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + if (check_compatibility(struct_addr, strings_addr, "brcm,bcm2835-gpio") == 0) + return; + print_node(struct_addr, strings_addr, depth); +} + +void rtx3080ti_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + if (check_compatibility(struct_addr, strings_addr, "rtx3080ti") == 0) return; + print_node(struct_addr, strings_addr, depth); +} + +void default_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + print_node(struct_addr, strings_addr, depth); +} + +int check_compatibility(uint64_t struct_addr, uint64_t strings_addr, + char *compatible_name) { + char *name = (char *)(struct_addr); + struct_addr += strlen(name) + 1; + struct_addr = align_up(struct_addr, 4); + + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_PROP) { + uint32_t len = dtb_read_int(struct_addr); + len = be2le(len); + struct_addr += 4; + uint32_t nameoff = dtb_read_int(struct_addr); + nameoff = be2le(nameoff); + struct_addr += 4; + char *property = (char *)(strings_addr + nameoff); + + if (strcmp(property, "compatible") == 0) { + uint64_t end = struct_addr + len; + while (struct_addr < end) { + char *string = (char *)struct_addr; + struct_addr += strlen(string) + 1; + if (strcmp(string, compatible_name) == 0) return 1; + } + return 0; + } else { + struct_addr += len; + struct_addr = align_up(struct_addr, 4); + } + } else if (token == FDT_NOP) { + continue; + } else { + break; + } + } + return 0; +} + +void dtb_print(int all) { + uint64_t dtb_addr = *((uint64_t *)0x9000000); + printf("dtb_addr = %x\n",dtb_addr); + fdt_header *header = (fdt_header *)dtb_addr; + uint64_t struct_addr = dtb_addr + be2le(header->off_dt_struct); + uint64_t strings_addr = dtb_addr + be2le(header->off_dt_strings); + + if (all) { + dtb_parse(struct_addr, strings_addr, default_probe); + } else { + printf("\ndevice for mailbox driver function: \n"); + dtb_parse(struct_addr, strings_addr, mailbox_probe); + printf("\ndevice for gpio driver function: \n"); + dtb_parse(struct_addr, strings_addr, gpio_probe); + printf("\ndevice for rtx3080ti driver function: \n"); + dtb_parse(struct_addr, strings_addr, rtx3080ti_probe); + } +} + +void dtb_parse(uint64_t struct_addr, uint64_t strings_addr, + void (*callback)(uint64_t, uint64_t, int)) { + int depth = 0; + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + callback(struct_addr, strings_addr, depth); + struct_addr = ignore_current_node(struct_addr, strings_addr); + depth++; + } else if (token == FDT_END_NODE) { + depth--; + } else if (token == FDT_NOP) { + continue; + } else if (token == FDT_END) { + break; + } + } +} + +uint64_t ignore_current_node(uint64_t struct_addr, uint64_t strings_addr) { + char *name = (char *)(struct_addr); + struct_addr += strlen(name) + 1; + struct_addr = align_up(struct_addr, 4); + + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_END_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_PROP) { + uint32_t len = dtb_read_int(struct_addr); + len = be2le(len); + struct_addr += 4; + uint32_t nameoff = dtb_read_int(struct_addr); + nameoff = be2le(nameoff); + struct_addr += 4; + struct_addr += len; + struct_addr = align_up(struct_addr, 4); + } else if (token == FDT_NOP) { + continue; + } + } + return struct_addr; +} + +uint64_t print_node(uint64_t struct_addr, uint64_t strings_addr, int depth) { + char *name = (char *)(struct_addr); + struct_addr += strlen(name) + 1; + struct_addr = align_up(struct_addr, 4); + for (int i = 0; i < depth; i++) printf(" "); + printf("node: %s\n", name); + + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + break; + } else if (token == FDT_END_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_PROP) { + struct_addr = print_property(struct_addr, strings_addr, depth + 1); + } else if (token == FDT_NOP) { + continue; + } + } + return struct_addr; +} + +uint64_t print_property(uint64_t struct_addr, uint64_t strings_addr, + int depth) { + uint32_t len = dtb_read_int(struct_addr); + len = be2le(len); + struct_addr += 4; + uint32_t nameoff = dtb_read_int(struct_addr); + nameoff = be2le(nameoff); + struct_addr += 4; + char *property = (char *)(strings_addr + nameoff); + + int value_type = 0; + char *is_u32[] = {"phandle", "#address-cells", "#size-cells", "virtual-reg", + "interrupt-parent"}; + char *is_string[] = {"compatible", "model", "status", "name", "device_type"}; + + for (int i = 0; i < sizeof(is_u32) / sizeof(is_u32[0]); i++) { + if (strcmp(property, is_u32[i]) == 0) { + value_type = 1; + break; + } + } + for (int i = 0; i < sizeof(is_string) / sizeof(is_string[0]); i++) { + if (strcmp(property, is_string[i]) == 0) { + value_type = 2; + break; + } + } + + for (int i = 0; i < depth; i++) printf(" "); + printf("%s = ", property); + + // hex, e.g. <0x4600 0x100> + if (value_type == 0) { + int count = 0; + printf("<"); + for (uint32_t i = 0; i < len; i += 4) { + if (count > 0) printf(" "); + count++; + uint32_t num = dtb_read_int(struct_addr); + num = be2le(num); + struct_addr += 4; + printf("0x%x", num); + } + printf(">"); + } + // int, e.g. <1> + if (value_type == 1) { + uint32_t num = dtb_read_int(struct_addr); + num = be2le(num); + struct_addr += 4; + printf("<%d>", num); + } + // string or string list, e.g. "fsl,MPC8349EMITX" or "fsl,mpc8641", "ns16550" + if (value_type == 2) { + int count = 0; + uint64_t end = struct_addr + len; + + while (struct_addr < end) { + if (count > 0) printf(", "); + count++; + char *string = (char *)struct_addr; + struct_addr += strlen(string) + 1; + printf("\"%s\"", string); + } + } + printf("\n"); + + struct_addr = align_up(struct_addr, 4); + return struct_addr; +} + +uint32_t dtb_read_int(uint64_t addr_ptr) { + char *base = (char *)(addr_ptr); + uint32_t value = 0; + for (int i = 3; i >= 0; i--) { + value = (value << 8) | (*(base + i) & 0xFF); + } + return value; +} + +// char *dtb_read_string(uint64_t addr_ptr) { +// char *base = (char *)(addr_ptr); +// char *string_start = base; +// return string_start; +// } \ No newline at end of file diff --git a/lab7/kernel/src/exception.S b/lab7/kernel/src/exception.S new file mode 100644 index 000000000..9ef00764b --- /dev/null +++ b/lab7/kernel/src/exception.S @@ -0,0 +1,127 @@ +// save general registers to stack +.macro save_reg + sub sp, sp, 32 * 9 + stp x0, x1, [sp, 16 * 0] + stp x2, x3, [sp, 16 * 1] + stp x4, x5, [sp, 16 * 2] + stp x6, x7, [sp, 16 * 3] + stp x8, x9, [sp, 16 * 4] + stp x10, x11, [sp, 16 * 5] + stp x12, x13, [sp, 16 * 6] + stp x14, x15, [sp, 16 * 7] + stp x16, x17, [sp, 16 * 8] + stp x18, x19, [sp, 16 * 9] + stp x20, x21, [sp, 16 * 10] + stp x22, x23, [sp, 16 * 11] + stp x24, x25, [sp, 16 * 12] + stp x26, x27, [sp, 16 * 13] + stp x28, x29, [sp, 16 * 14] + //str x30, [sp, 16 * 15] + mrs x10, spsr_el1 + mrs x11, elr_el1 + mrs x12, sp_el0 + stp x30, x10, [sp, 16 * 15] + stp x11, x12, [sp, 16 * 16] +.endm + +// load general registers from stack +.macro load_reg + ldp x30, x10, [sp, 16 * 15] + ldp x11, x12, [sp, 16 * 16] + msr spsr_el1, x10 + msr elr_el1, x11 + msr sp_el0, x12 + ldp x0, x1, [sp, 16 * 0] + ldp x2, x3, [sp, 16 * 1] + ldp x4, x5, [sp, 16 * 2] + ldp x6, x7, [sp, 16 * 3] + ldp x8, x9, [sp, 16 * 4] + ldp x10, x11, [sp, 16 * 5] + ldp x12, x13, [sp, 16 * 6] + ldp x14, x15, [sp, 16 * 7] + ldp x16, x17, [sp, 16 * 8] + ldp x18, x19, [sp, 16 * 9] + ldp x20, x21, [sp, 16 * 10] + ldp x22, x23, [sp, 16 * 11] + ldp x24, x25, [sp, 16 * 12] + ldp x26, x27, [sp, 16 * 13] + ldp x28, x29, [sp, 16 * 14] + //ldr x30, [sp, 16 * 15] + //ldp x30, x10, [sp, 16 * 15] + //ldp x11, x12, [sp, 16 * 16] + //msr spsr_el1, x10 + //msr elr_el1, x11 + //msr sp_el0, x12 + add sp, sp, 32 * 9 +.endm + +.align 11 // vector table should be aligned to 0x800 +.global exception_vector_table +exception_vector_table: + b _default_handler // branch to a handler function. + .align 7 // entry size is 0x80, .align will pad 0 + b _default_handler + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + + b _sync_handler_currentEL_ELx + .align 7 + b _irq_handler_currentEL_ELx + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + + b _sync_handler_lowerEL_64 + .align 7 + b _irq_handler_lowerEL_64 + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + + b _default_handler + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + +_sync_handler_currentEL_ELx: + save_reg + bl sync_handler_currentEL_ELx // exception.c + load_reg + eret + +_sync_handler_lowerEL_64: + save_reg + //mrs x0, sp_el0 + mov x0, sp + bl sync_handler_lowerEL_64 // exception.c + load_reg + eret + +_irq_handler_currentEL_ELx: + save_reg + bl irq_handler_currentEL_ELx // exception.c + load_reg + eret + +_irq_handler_lowerEL_64: + save_reg + bl irq_handler_lowerEL_64 // exception.c + load_reg + eret + +_default_handler: + save_reg + bl default_handler // exception.c + load_reg + eret \ No newline at end of file diff --git a/lab7/kernel/src/exception.c b/lab7/kernel/src/exception.c new file mode 100644 index 000000000..f56fce893 --- /dev/null +++ b/lab7/kernel/src/exception.c @@ -0,0 +1,177 @@ +#include "exception.h" +#include "uart.h" +#include "utils.h" +#include "timer.h" +#include "string.h" +#include "thread.h" +#include "printf.h" +#include "mbox.h" +#include "vfs.h" +#include "device.h" + +int count = 0; + +void enable_interrupt() { asm volatile("msr DAIFClr, 0xf"); } + +void disable_interrupt() { asm volatile("msr DAIFSet, 0xf"); } + +void sync_handler_currentEL_ELx() { + printf("[sync_handler_currentEL_ELx]\n"); + + uint64_t spsr_el1, elr_el1, esr_el1; + asm volatile("mrs %0, spsr_el1" : "=r"(spsr_el1)); + asm volatile("mrs %0, elr_el1" : "=r"(elr_el1)); + asm volatile("mrs %0, esr_el1" : "=r"(esr_el1)); + while(1); +} + +void sync_handler_lowerEL_64(uint64_t sp) { + // printf("sync_handler_lowerEL_64 sp : %x\n",sp); + uint64_t spsr_el1, elr_el1, esr_el1; + asm volatile("mrs %0, spsr_el1" : "=r"(spsr_el1)); + asm volatile("mrs %0, elr_el1" : "=r"(elr_el1)); + asm volatile("mrs %0, esr_el1" : "=r"(esr_el1)); + // printf("sync, SPSR_EL1: 0x%08x\n", spsr_el1); + // printf("ELR_EL1: 0x%08x\n", elr_el1); + // printf("ESR_EL1: 0x%08x\n", esr_el1); + + uint32_t ec = (esr_el1 >> 26) & 0x3f; + // printf("EC: %x\n", ec); + if (ec == 0b010101) { // SVC instruction + // printf("pid = %d, ",get_current()->pid); + uint64_t iss; + asm volatile("mov %0, x8" : "=r"(iss)); + // printf("syscall number: %d\n", iss); + trap_frame_t *trap_frame = (trap_frame_t *)sp; + + if (iss == 0) { // getpid + uint32_t pid = get_current()->pid; + trap_frame->x[0] = pid; + } else if (iss == 1) { // uartread + // printf("[read]\n"); + disable_uart_interrupt(); + enable_interrupt(); + char *str = (char *)(trap_frame->x[0]); + uint32_t size = (uint32_t)(trap_frame->x[1]); + size = uart_gets(str, size); + trap_frame->x[0] = size; + } else if (iss == 2) { // uartwrite + // printf("[write]\n"); + char *str = (char *)(trap_frame->x[0]); + trap_frame->x[0] = uart_write(str,trap_frame->x[1]); + } else if (iss == 3) { // exec + const char *program_name = (const char *)trap_frame->x[0]; + const char **argv = (const char **)trap_frame->x[1]; + exec(program_name, argv); + } else if (iss == 4) { // fork + // printf("[fork]\n"); + fork(sp); + } else if (iss == 5) { // exit + exit(); + } else if (iss == 6) { // mbox_call + printf("\n\n\n[mbox_call]\n"); + trap_frame->x[0] = mbox_call(trap_frame->x[0],(unsigned int *)trap_frame->x[1]); + } else if (iss == 7) { // kill + kill((int)trap_frame->x[0]); + } //vfs + else if (iss == 11) { // open + printf("[open]%s\n",(const char *)trap_frame->x[0]); + struct file* file = vfs_open((const char *)trap_frame->x[0],trap_frame->x[1]); + int fd = thread_register_fd(file); + printf("[open]fd :%d\n",fd); + + trap_frame->x[0] = fd; + + } else if (iss == 12) { // close + printf("[close]fd =%d\n",trap_frame->x[0]); + struct file* file = thread_get_file(trap_frame->x[0]); + vfs_close(file); + + } else if (iss == 13) { // write + // remember to return read size or error code + // printf("[write]\n"); + // printf("[write]fd =%d\n",trap_frame->x[0]); + // printf("[write]write_buf =%s\n",trap_frame->x[1]); + // printf("[write]size =%d\n",trap_frame->x[2]); + struct file* file = thread_get_file(trap_frame->x[0]); + trap_frame->x[0] = vfs_write(file, (const void *)trap_frame->x[1], trap_frame->x[2]); + + } else if (iss == 14) { // read + // remember to return read size or error code + printf("[read]\n"); + printf("[read]id =%d\n",trap_frame->x[0]); + printf("[read]read_buf =%s\n",trap_frame->x[1]); + printf("[read]size =%d\n",trap_frame->x[2]); + struct file* file = thread_get_file(trap_frame->x[0]); + trap_frame->x[0] = vfs_read(file, (void *)trap_frame->x[1], trap_frame->x[2]); + printf("[read][after] read_buf =%s\n",trap_frame->x[1]); + + } else if (iss == 15) { // mkdir + // you can ignore mode, since there is no access control + printf("[mkdir]%s\n",(const char *)trap_frame->x[0]); + trap_frame->x[0] = vfs_mkdir((const char *)trap_frame->x[0]); + + } else if (iss == 16) { // mount + // you can ignore arguments other than target (where to mount) and filesystem (fs name) + const char *device = (const char *)trap_frame->x[0]; + const char *mountpoint = (const char *)trap_frame->x[1]; + const char *filesystem = (const char *)trap_frame->x[2]; + printf("[mount]mountpoint %s\n", mountpoint); + printf("[mount]filesystem %s\n", filesystem); + + int result = vfs_mount(device, mountpoint, filesystem); + trap_frame->x[0] = result; + + } else if (iss == 17) { // chdir + const char *pathname = (const char *)trap_frame->x[0]; + printf("[chdir]%s\n", pathname); + + int result = vfs_chdir(pathname); + trap_frame->x[0] = result; + } else if (iss == 18) { // lseek64 + // printf("[lseek64]\n"); + // printf("[lseek64]fd = %d\n", trap_frame->x[0]); + // printf("[lseek64]offset = %ld\n", (long) trap_frame->x[1]); + // printf("[lseek64]whence = %d\n", trap_frame->x[2]); + trap_frame->x[0] = lseek64(trap_frame->x[0], trap_frame->x[1], trap_frame->x[2]); + } else if (iss == 19) { // ioctl + printf("[ioctl]\n"); + printf("[ioctl]fd = %d\n", trap_frame->x[0]); + printf("[ioctl]request = %ld\n", (long) trap_frame->x[1]); + trap_frame->x[0] = ioctl(trap_frame->x[0], trap_frame->x[1], (struct framebuffer_info*)trap_frame->x[2]); + } + } +} + + +void irq_handler_currentEL_ELx() { + // printf("====irq_handler_currentEL_ELx=====\n"); + + disable_interrupt(); + uint32_t is_uart = (*IRQ_PENDING_1 & AUX_IRQ); + uint32_t is_core_timer = (*CORE0_INTERRUPT_SOURCE & 0x2); + + if (is_uart) { + uart_handler(); + } else if (is_core_timer) { + core_timer_handler_lowerEL_64(); + } + enable_interrupt(); +} + +void irq_handler_lowerEL_64() { + // printf("====irq_handler_lowerEL_64=====\n"); + disable_interrupt(); + uint32_t is_uart = (*IRQ_PENDING_1 & AUX_IRQ); + uint32_t is_core_timer = (*CORE0_INTERRUPT_SOURCE & 0x2); + + if (is_uart) { + uart_handler(); + } else if (is_core_timer) { + core_timer_handler_lowerEL_64(); + } + enable_interrupt(); +} + + +void default_handler() { uart_puts("===== default handler =====\n"); } diff --git a/lab7/kernel/src/linker.ld b/lab7/kernel/src/linker.ld new file mode 100644 index 000000000..ef09ab120 --- /dev/null +++ b/lab7/kernel/src/linker.ld @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +SECTIONS +{ + . = 0x80000; + .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) } + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) } + PROVIDE(_data = .); + .data : { *(.data .data.* .gnu.linkonce.d*) } + .bss (NOLOAD) : { + . = ALIGN(16); + __bss_start = .; + *(.bss .bss.*) + *(COMMON) + __bss_end = .; + } + _end = .; + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} +__bss_size = (__bss_end - __bss_start)>>3; \ No newline at end of file diff --git a/lab7/kernel/src/main.c b/lab7/kernel/src/main.c new file mode 100644 index 000000000..3275b2877 --- /dev/null +++ b/lab7/kernel/src/main.c @@ -0,0 +1,32 @@ +#include "uart.h" +#include "string.h" +#include "power.h" +#include "mbox.h" +#include "cpio.h" +#include "timer.h" +#include "exception.h" +#include "alloc.h" +#include "utils.h" +#include "thread.h" +#include "printf.h" +#include "shell.h" +#include "vfs.h" + +// #include "device_tree.h" +void main() +{ + // set up serial console + uart_init(); + buddy_init(); + //welcome message + uart_puts("*****************************\r\n"); + uart_puts("* welcome OSC2022 *\r\n"); + uart_puts("*****************************\r\n"); + timeout_event_init(); + enable_interrupt(); + // thread_init(); + vfs_init(); + thread_init(); + run_shell(); +} + diff --git a/lab7/kernel/src/math.c b/lab7/kernel/src/math.c new file mode 100644 index 000000000..2b89b515c --- /dev/null +++ b/lab7/kernel/src/math.c @@ -0,0 +1,9 @@ +int pow(int base, int exponent) +{ + int result = 1; + for ( ; exponent > 0; exponent--) + { + result = result * base; + } + return result; +} \ No newline at end of file diff --git a/lab7/kernel/src/mbox.c b/lab7/kernel/src/mbox.c new file mode 100644 index 000000000..f0ce82048 --- /dev/null +++ b/lab7/kernel/src/mbox.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" + +/* mailbox message buffer */ +volatile unsigned int __attribute__((aligned(16))) mbox[36]; + +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) +#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) +#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) +#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) +#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) +#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) +#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) +#define MBOX_RESPONSE 0x80000000 +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 + +/** + * Make a mailbox call. Returns 0 on failure, non-zero on success + */ +int mbox_call(unsigned char ch, unsigned int *user_mbox) +{ + unsigned int r = (((unsigned int)((unsigned long)user_mbox)&~0xF) | (ch&0xF)); + /* wait until we can write to the mailbox */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_FULL); + /* write the address of our message to the mailbox with channel identifier */ + *MBOX_WRITE = r; + /* now wait for the response */ + while(1) { + /* is there a response? */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY); + /* is it a response to our message? */ + if(r == *MBOX_READ) + /* is it a valid successful response? */ + return user_mbox[1]==MBOX_RESPONSE; + } + return 0; +} diff --git a/lab7/kernel/src/power.c b/lab7/kernel/src/power.c new file mode 100644 index 000000000..c066b6259 --- /dev/null +++ b/lab7/kernel/src/power.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" +#include "mbox.h" +#include "delays.h" + +#define PM_RSTC ((volatile unsigned int*)(MMIO_BASE+0x0010001c)) +#define PM_RSTS ((volatile unsigned int*)(MMIO_BASE+0x00100020)) +#define PM_WDOG ((volatile unsigned int*)(MMIO_BASE+0x00100024)) +#define PM_WDOG_MAGIC 0x5a000000 +#define PM_RSTC_FULLRST 0x00000020 + +/** + * Shutdown the board + */ +void power_off() +{ + unsigned long r; + + // power off devices one by one + for(r=0;r<16;r++) { + mbox[0]=8*4; + mbox[1]=MBOX_REQUEST; + mbox[2]=MBOX_TAG_SETPOWER; // set power state + mbox[3]=8; + mbox[4]=8; + mbox[5]=(unsigned int)r; // device id + mbox[6]=0; // bit 0: off, bit 1: no wait + mbox[7]=MBOX_TAG_LAST; + mbox_call(MBOX_CH_PROP,mbox); + } + + // power off gpio pins (but not VCC pins) + *GPFSEL0 = 0; *GPFSEL1 = 0; *GPFSEL2 = 0; *GPFSEL3 = 0; *GPFSEL4 = 0; *GPFSEL5 = 0; + *GPPUD = 0; + wait_cycles(150); + *GPPUDCLK0 = 0xffffffff; *GPPUDCLK1 = 0xffffffff; + wait_cycles(150); + *GPPUDCLK0 = 0; *GPPUDCLK1 = 0; // flush GPIO setup + + // power off the SoC (GPU + CPU) + r = *PM_RSTS; r &= ~0xfffffaaa; + r |= 0x555; // partition 63 used to indicate halt + *PM_RSTS = PM_WDOG_MAGIC | r; + *PM_WDOG = PM_WDOG_MAGIC | 10; + *PM_RSTC = PM_WDOG_MAGIC | PM_RSTC_FULLRST; +} + +/** + * Reboot + */ +void reset() +{ + unsigned int r; + // trigger a restart by instructing the GPU to boot from partition 0 + r = *PM_RSTS; r &= ~0xfffffaaa; + *PM_RSTS = PM_WDOG_MAGIC | r; // boot from partition 0 + *PM_WDOG = PM_WDOG_MAGIC | 10; + *PM_RSTC = PM_WDOG_MAGIC | PM_RSTC_FULLRST; +} diff --git a/lab7/kernel/src/printf.c b/lab7/kernel/src/printf.c new file mode 100644 index 000000000..13b92a7b4 --- /dev/null +++ b/lab7/kernel/src/printf.c @@ -0,0 +1,921 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. These routines are thread +// safe and reentrant! +// Use this instead of the bloated standard/newlib printf cause these use +// malloc for printf (and may not be thread safe). +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "printf.h" + + +// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the +// printf_config.h header file +// default: undefined +#ifdef PRINTF_INCLUDE_CONFIG_H +#include "printf_config.h" +#endif + + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +// support for the floating point type (%f) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +// support for exponential floating point notation (%e/%g) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL +#define PRINTF_SUPPORT_EXPONENTIAL +#endif + +// define the default floating point precision +// default: 6 digits +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +// define the largest float suitable to print with %f +// default: 1e9 +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +// support for the long long types (%llu or %p) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +// support for the ptrdiff_t type (%t) +// ptrdiff_t is normally defined in as long or long long type +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + + +// import float.h for DBL_MAX +#if defined(PRINTF_SUPPORT_FLOAT) +#include +#endif + +// my custom implementation of _putchar +#include "uart.h" +void _putchar(char character) { + if (character == '\n') uart_send('\r'); + uart_send(character); +} + + +// output function type +typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); + + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void* arg); + void* arg; +} out_fct_wrap_type; + + +// internal buffer output +static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) +{ + if (idx < maxlen) { + ((char*)buffer)[idx] = character; + } +} + + +// internal null output +static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)character; (void)buffer; (void)idx; (void)maxlen; +} + + +// internal _putchar wrapper +static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)buffer; (void)idx; (void)maxlen; + if (character) { + _putchar(character); + } +} + + +// internal output function wrapper +static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)idx; (void)maxlen; + if (character) { + // buffer is the output fct pointer + ((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg); + } +} + + +// internal secure strlen +// \return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int _strnlen_s(const char* str, size_t maxsize) +{ + const char* s; + for (s = str; *s && maxsize--; ++s); + return (unsigned int)(s - str); +} + + +// internal test if char is a digit (0-9) +// \return true if char is a digit +static inline bool _is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + + +// internal ASCII string to unsigned int conversion +static unsigned int _atoi(const char** str) +{ + unsigned int i = 0U; + while (_is_digit(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + + +// output the specified string in reverse, taking care of any zero-padding +static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) +{ + const size_t start_idx = idx; + + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + + +// internal itoa format +static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) +{ + // pad leading zeros + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + // handle hash + if (flags & FLAGS_HASH) { + if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { + len--; + if (len && (base == 16U)) { + len--; + } + } + if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } + else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } + else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_NTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +// internal itoa for 'long' type +static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} + + +// internal itoa for 'long long' type +#if defined(PRINTF_SUPPORT_LONG_LONG) +static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#endif // PRINTF_SUPPORT_LONG_LONG + + +#if defined(PRINTF_SUPPORT_FLOAT) + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags); +#endif + + +// internal ftoa for fixed decimal floating point +static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + + // powers of 10 + static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + + // test for special values + if (value != value) + return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + // test for very large values + // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad + if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); +#else + return 0U; +#endif + } + + // test for negative + bool negative = false; + if (value < 0) { + negative = true; + value = 0 - value; + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + // limit precision to 9, cause a prec >= 10 can lead to overflow errors + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { + buf[len++] = '0'; + prec--; + } + + int whole = (int)value; + double tmp = (value - whole) * pow10[prec]; + unsigned long frac = (unsigned long)tmp; + diff = tmp - frac; + + if (diff > 0.5) { + ++frac; + // handle rollover, e.g. case 0.99 with prec 1 is 1.0 + if (frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } + else if (diff < 0.5) { + } + else if ((frac == 0U) || (frac & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++frac; + } + + if (prec == 0U) { + diff = value - (double)whole; + if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++whole; + } + } + else { + unsigned int count = prec; + // now do fractional part, as an unsigned number + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(48U + (frac % 10U)); + if (!(frac /= 10U)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + // add decimal + buf[len++] = '.'; + } + } + + // do whole part, number is reversed + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(48 + (whole % 10)); + if (!(whole /= 10)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + // check for NaN and special values + if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { + return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); + } + + // determine the sign + const bool negative = value < 0; + if (negative) { + value = -value; + } + + // default precision + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // determine the decimal exponent + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + union { + uint64_t U; + double F; + } conv; + + conv.F = value; + int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 + conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) + // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 + int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^expval but we want to be sure it won't overflow + exp2 = (int)(expval * 3.321928094887362 + 0.5); + const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = (uint64_t)(exp2 + 1023) << 52U; + // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if (value < conv.F) { + expval--; + conv.F /= 10; + } + + // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters + unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; + + // in "%g" mode, "prec" is the number of *significant figures* not decimals + if (flags & FLAGS_ADAPT_EXP) { + // do we want to fall-back to "%f" mode? + if ((value >= 1e-4) && (value < 1e6)) { + if ((int)prec > expval) { + prec = (unsigned)((int)prec - expval - 1); + } + else { + prec = 0; + } + flags |= FLAGS_PRECISION; // make sure _ftoa respects precision + // no characters in exponent + minwidth = 0U; + expval = 0; + } + else { + // we use one sigfig for the whole part + if ((prec > 0) && (flags & FLAGS_PRECISION)) { + --prec; + } + } + } + + // will everything fit? + unsigned int fwidth = width; + if (width > minwidth) { + // we didn't fall-back so subtract the characters required for the exponent + fwidth -= minwidth; + } else { + // not enough characters, so go back to default sizing + fwidth = 0U; + } + if ((flags & FLAGS_LEFT) && minwidth) { + // if we're padding on the right, DON'T pad the floating part + fwidth = 0U; + } + + // rescale the float value + if (expval) { + value /= conv.F; + } + + // output the floating part + const size_t start_idx = idx; + idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); + + // output the exponent part + if (minwidth) { + // output the exponential symbol + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + // output the exponent value + idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS); + // might need to right-pad spaces + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + + +// internal vsnprintf +static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) +{ + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + // use null output function + out = _out_null; + } + + while (*format) + { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } + else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break; + case '-': flags |= FLAGS_LEFT; format++; n = 1U; break; + case '+': flags |= FLAGS_PLUS; format++; n = 1U; break; + case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break; + case '#': flags |= FLAGS_HASH; format++; n = 1U; break; + default : n = 0U; break; + } + } while (n); + + // evaluate width field + width = 0U; + if (_is_digit(*format)) { + width = _atoi(&format); + } + else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } + else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (_is_digit(*format)) { + precision = _atoi(&format); + } + else if (*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l' : + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h' : + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't' : + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j' : + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z' : + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default : + break; + } + + // evaluate specifier + switch (*format) { + case 'd' : + case 'i' : + case 'u' : + case 'x' : + case 'X' : + case 'o' : + case 'b' : { + // set the base + unsigned int base; + if (*format == 'x' || *format == 'X') { + base = 16U; + } + else if (*format == 'o') { + base = 8U; + } + else if (*format == 'b') { + base = 2U; + } + else { + base = 10U; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + } + else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags); + } + else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); + idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f' : + case 'F' : + if (*format == 'F') flags |= FLAGS_UPPERCASE; + idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + case 'c' : { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's' : { + const char* p = va_arg(va, char*); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p' : { + width = sizeof(void*) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + const bool is_ll = sizeof(uintptr_t) == sizeof(long long); + if (is_ll) { + idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags); + } + else { +#endif + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%' : + out('%', buffer, idx++, maxlen); + format++; + break; + + default : + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + + +/////////////////////////////////////////////////////////////////////////////// + +int printf_(const char* format, ...) +{ + va_list va; + va_start(va, format); + char buffer[1]; + const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + +int sprintf_(char* buffer, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + +int snprintf_(char* buffer, size_t count, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); + va_end(va); + return ret; +} + + +int vprintf_(const char* format, va_list va) +{ + char buffer[1]; + return _vsnprintf(_out_char, buffer, (size_t)-1, format, va); +} + + +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va) +{ + return _vsnprintf(_out_buffer, buffer, count, format, va); +} + + +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) +{ + va_list va; + va_start(va, format); + const out_fct_wrap_type out_fct_wrap = { out, arg }; + const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va); + va_end(va); + return ret; +} \ No newline at end of file diff --git a/lab7/kernel/src/shell.c b/lab7/kernel/src/shell.c new file mode 100644 index 000000000..834b7c9e8 --- /dev/null +++ b/lab7/kernel/src/shell.c @@ -0,0 +1,251 @@ +#include "uart.h" +#include "string.h" +#include "power.h" +#include "mbox.h" +#include "cpio.h" +#include "timer.h" +#include "exception.h" +#include "alloc.h" +#include "utils.h" +#include "thread.h" +#include "printf.h" +#include "dtb.h" +#include "vfs.h" + +void clean_buffer(char * buffer, int buffer_len) +{ + for(int i = 0 ; i < buffer_len ; i++) + buffer[i] = '\0'; +} + +void command_help() +{ + uart_puts("This is kernel shell\n"); + uart_puts("help\t\t: print this help menu\n"); + uart_puts("hello\t\t: print Hello World!\n"); + uart_puts("reboot\t\t: reboot the device\n"); + uart_puts("mailbox\t\t: show information through mailbox\n"); + uart_puts("dtb\t\t: parse device tree message\n"); + uart_puts("dtb all\t\t: parse device tree message\n"); + uart_puts("ls\t\t: show all files\n"); + uart_puts("cat\t\t: show file info\n"); + uart_puts("test\t\t: test simple allocator\n"); + uart_puts("user\t\t: load and run a user program in the initramfs\n"); + uart_puts("timer\t\t: core_timer_enable\n"); + uart_puts("puts\t\t: async_puts Test Message\n"); + uart_puts("buddy test\t: test for buddy system\n"); + uart_puts("dma test \t: test for dynamic memory allocation\n"); + uart_puts("setTimeout [MESSAGE] [SECONDS]\t: prints MESSAGE after SECONDS\n"); +} + +void command_hello() +{ + uart_puts("\n"); + uart_puts("Hello World!\n"); +} + +void command_not_found(char * buffer) +{ + uart_puts("\n"); + uart_puts("command *"); + uart_puts(buffer); + uart_puts("* not exist\n"); +} + +void command_ls(){ + cpio_ls(); +} + + +void command_cat(char* pathname){ + cpio_cat(pathname); +} + +void command_mailbox() +{ + // get serail number + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETSERIAL; // get serial number command + mbox[3] = 8; // buffer size + mbox[4] = 8; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + uart_puts("\n"); + if (mbox_call(MBOX_CH_PROP,mbox)) { + uart_puts("serial number is: "); + uart_hex(mbox[6]); + uart_hex(mbox[5]); + uart_puts("\n"); + } + // get board revision + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETBDVS; // get board revision + mbox[3] = 4; // buffer size + mbox[4] = 4; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + if (mbox_call(MBOX_CH_PROP,mbox)) { + uart_puts("board revision is: "); + uart_hex(mbox[6]); + uart_hex(mbox[5]); + uart_puts("\n"); + } + + // get arm memory + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETARMMEM; // get arm memory info + mbox[3] = 8; // buffer size + mbox[4] = 8; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + if (mbox_call(MBOX_CH_PROP,mbox)) { + uart_puts("arm base addr: "); + uart_hex(mbox[5]); + uart_puts("\n"); + uart_puts("arm addr size: "); + uart_hex(mbox[6]); + uart_puts("\n"); + } +} + +void command_test() +{ + // test malloc + uart_puts("\r"); + uart_puts("test malloc\n"); + char * c = malloc(30); + c[0]='a'; + c[1]='b'; + c[2]='\0'; + uart_puts("c:"); + uart_puts(c); + uart_puts("\r\n"); + char * d = malloc(30); + d[0]='x'; + d[1]='y'; + d[2]='\0'; + uart_puts("d:"); + uart_puts(d); + uart_puts("\r\n"); +} + +void command_load_user_program(const char *program_name) { + uint64_t spsr_el1 = 0x0; // EL0t with interrupt enabled + uint64_t target_addr = 0x30100000; + uint64_t target_sp = 0x10007030; + cpio_load_user_program(program_name, target_addr); + // core_timer_enable(); + asm volatile("msr spsr_el1, %0" : : "r"(spsr_el1)); + asm volatile("msr elr_el1, %0" : : "r"(target_addr)); + asm volatile("msr sp_el0, %0" : : "r"(target_sp)); + asm volatile("eret"); +} + +void command_set_timeout(char *args) { + uint32_t duration = 0; + for (int i = 0; args[i]; i++) { + if (args[i] == ' ') { + for (int j = i + 1; args[j]; j++) { + duration = duration * 10 + (args[j] - '0'); + } + args[i] = '\0'; + break; + } + } + add_timer(timer_callback, args, duration); +} + +void command_buddy_test() { + buddy_test(); +} +void command_dma_test() { + dma_test(); +} +void command_thread_test1() { + thread_test1(); +} +void command_thread_test2() { + thread_test2(); +} +void command_thread_test3() { + thread_test3(); +} +void command_thread_test4() { + thread_test4(); +} + +void commandd_vfs_test() { vfs_test(); } + + +void command_dtb_print(int all) { dtb_print(all); } + +void parse_command(char * buffer) +{ + if ( !strcmp(buffer, "help")) command_help(); + else if ( !strcmp(buffer, "hello")) command_hello(); + else if ( !strcmp(buffer, "mailbox")) command_mailbox(); + else if ( !strcmp(buffer, "ls")) command_ls(); + else if ( !strncmp(buffer, "cat", 3)) command_cat(&buffer[4]); + else if ( !strcmp(buffer, "test")) command_test(); + else if ( !strcmp(buffer, "reboot")) reset(); + else if ( !strncmp(buffer, "run", 3)) command_load_user_program(&buffer[4]); + else if ( !strcmp(buffer, "puts")) uart_async_puts("Test Message!\n"); + else if ( !strcmp(buffer, "timer")) core_timer_enable(); + else if ( !strncmp(buffer, "setTimeout", 10)) command_set_timeout(&buffer[11]); + else if ( !strcmp(buffer, "buddy test")) command_buddy_test(); + else if ( !strcmp(buffer, "dma test")) command_dma_test(); + else if ( !strcmp(buffer, "dtb")) command_dtb_print(0); + else if ( !strcmp(buffer, "dtb all")) command_dtb_print(1); + else if ( !strcmp(buffer, "t1")) command_thread_test1(); + else if ( !strcmp(buffer, "t2")) command_thread_test2(); + else if ( !strcmp(buffer, "t3")) command_thread_test3(); + else if ( !strcmp(buffer, "t4")) command_thread_test4(); + else if ( !strcmp(buffer, "vfs")) vfs_test(); + else command_not_found(buffer); +} + +void run_shell() +{ + char buffer[64]={'\0'}; + int buffer_len=0; + //clean buffer + clean_buffer(buffer, 64); + // echo everything back + while(1) { + printf("# "); + while(1){ + char c = uart_async_getc(); + if(c=='\n')uart_send('\r'); + uart_send(c); + if(c=='\n'){ + //parse buffer + parse_command(buffer); + //clean buffer + clean_buffer(buffer, 64); + buffer_len = 0; + break; + } + //backspace + if (c == 127) { + if (buffer_len > 0) { + printf("\b \b"); + buffer[--buffer_len] = '\0'; + } + continue; + } + buffer[buffer_len++] = c; + } + } +} diff --git a/lab7/kernel/src/start.S b/lab7/kernel/src/start.S new file mode 100644 index 000000000..ccc0e40fb --- /dev/null +++ b/lab7/kernel/src/start.S @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +.section ".text.boot" + +.global _start + +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #3 + cbz x1, master + b hang_loop // cpu id > 0, stop + +master: // cpu id == 0 + + // save dtb loading address + ldr x1, =0x9000000 + str x0, [x1] + + bl from_el2_to_el1 + bl set_exception_vector_table + + // clear bss + ldr x1, =__bss_start + ldr w2, =__bss_size + +clear_bss_start: + cbz w2, clear_bss_done + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, clear_bss_start + + +clear_bss_done: + // set top of stack just before our code (stack grows to a lower address per AAPCS64) + ldr x1, =_start + mov sp, x1 + + bl main // jump to C code, should not return + b hang_loop // for failsafe, halt this core too + +from_el2_to_el1: + mov x0, (1 << 31) // EL1 uses aarch64 + msr hcr_el2, x0 + mov x0, 0x3c5 // EL1h with interrupt disabled + msr spsr_el2, x0 + msr elr_el2, lr + + // IMPORTANT: disable exceptions of accessing the SIMD and floating-point registers + mov x0, #(3 << 20) + msr cpacr_el1, x0 + + eret // return to EL1 + +set_exception_vector_table: + adr x0, exception_vector_table + msr vbar_el1, x0 + ret + +hang_loop: + wfe + b hang_loop \ No newline at end of file diff --git a/lab7/kernel/src/string.c b/lab7/kernel/src/string.c new file mode 100644 index 000000000..aa38ba5bf --- /dev/null +++ b/lab7/kernel/src/string.c @@ -0,0 +1,165 @@ +#include "string.h" + +/* Compare S1 and S2, returning less than, equal to or + greater than zero if S1 is lexicographically less than, + equal to or greater than S2. */ +int strcmp(const char *p1, const char *p2) { + const unsigned char *s1 = (const unsigned char *)p1; + const unsigned char *s2 = (const unsigned char *)p2; + unsigned char c1, c2; + do { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0') return c1 - c2; + } while (c1 == c2); + return c1 - c2; +} + +/* Compare no more than N characters of S1 and S2, + returning less than, equal to or greater than zero + if S1 is lexicographically less than, equal to or + greater than S2. */ +int strncmp(const char *s1, const char *s2, unsigned n) { + unsigned char c1 = '\0'; + unsigned char c2 = '\0'; + if (n >= 4) { + unsigned n4 = n >> 2; + do { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + } while (--n4 > 0); + n &= 3; + } + while (n > 0) { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + n--; + } + return c1 - c2; +} + +int strlen(const char *s) { + int len = 0; + while (s[len] != '\0') { + len++; + } + return len; +} + +/* + * Find the first occurrence of find in s. + */ +char *strstr(const char *s, const char *find) { + char c, sc; + int len; + if ((c = *find++) != 0) { + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) return 0; + } while (sc != c); + } while (strncmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} + +char *strcpy(char *dst, const char *src) { + // return if no memory is allocated to the destination + if (dst == 0) return 0; + + char *ptr = dst; + while (*src != '\0') { + *dst = *src; + dst++; + src++; + } + *dst = '\0'; + return ptr; +} + +char *strncpy(char *dst, const char *src, size_t len) { + // return if no memory is allocated to the destination + if (dst == 0) return 0; + + // take a pointer pointing to the beginning of destination string + char *ptr = dst; + + // copy the C-string pointed by source into the array + // pointed by destination + while (*src != ' ') { + *dst = *src; + dst++; + src++; + len--; + if (!len) { + break; + } + } + + // include the terminating null character + *dst = '\0'; + + // destination is returned by standard strcpy() + return ptr; +} + +void strcat(char *to, const char *from) { + while (*to) { + to++; + } + while (*from) { + *to = *from; + to++; + from++; + } + *to = '\0'; +} + +char *strtok(char *s, const char delim) { + static char *pos; + char *ret; + if (s) pos = s; + + if (*pos == '\0') return 0; + // skip leading + while (*pos == delim) { + pos++; + } + + ret = pos; + while (*pos != delim && *pos != '\0') { + pos++; + } + if (*pos != '\0') { + *pos = '\0'; + pos++; + } + return ret; +} + +char *split_last(char *str, char delim) { + char *mid = 0; + while (*str) { + if (*str == delim) { + mid = str; + } + str++; + } + if (mid) { + *mid = '\0'; + mid++; + } + return mid; +} \ No newline at end of file diff --git a/lab7/kernel/src/thread.S b/lab7/kernel/src/thread.S new file mode 100644 index 000000000..514958efa --- /dev/null +++ b/lab7/kernel/src/thread.S @@ -0,0 +1,26 @@ +.global switch_to +switch_to: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + + ldp x19, x20, [x1, 16 * 0] + ldp x21, x22, [x1, 16 * 1] + ldp x23, x24, [x1, 16 * 2] + ldp x25, x26, [x1, 16 * 3] + ldp x27, x28, [x1, 16 * 4] + ldp fp, lr, [x1, 16 * 5] + ldr x9, [x1, 16 * 6] + mov sp, x9 + msr tpidr_el1, x1 + ret + +.global get_current +get_current: + mrs x0, tpidr_el1 + ret \ No newline at end of file diff --git a/lab7/kernel/src/thread.c b/lab7/kernel/src/thread.c new file mode 100644 index 000000000..04c6a9550 --- /dev/null +++ b/lab7/kernel/src/thread.c @@ -0,0 +1,301 @@ +#include "thread.h" +#include "timer.h" +#include "alloc.h" +#include "cpio.h" +#include "exception.h" +#include "printf.h" +#include "utils.h" +#include "shell.h" + +void foo() { + for (int i = 0; i < 4; ++i) { + printf("Thread id: %d, %d\r\n", get_current()->pid, i); + delay(1000000); + schedule(); + } + exit(); + return; +} + +void user_test1() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("my_test", argv); +} + +void user_test2() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("my_test2", argv); +} +void user_test3() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("fork_test", argv); +} + +void user_test4() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("vfs1.img", argv); +} + +void user_test5() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("vm.img", argv); +} + +void thread_test1() { // thread test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test1); + thread_create(user_test2); + idle(); +} + +void thread_test2() { // fork test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test3); + idle(); +} + +void thread_test3() { //vedio player1 test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test4); + idle(); +} + +void thread_test4() { //vedio player1 test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test5); + idle(); +} + +void thread_init() { + run_queue.head = 0; + run_queue.tail = 0; + thread_cnt = 0; +} + +thread_info *thread_create(void (*func)()) { + // printf("create thread pid = %d\n",thread_cnt); + thread_info *thread = (thread_info *)malloc(sizeof(thread_info)); + thread->pid = thread_cnt++; + thread->status = THREAD_READY; + thread->next = 0; + thread->kernel_stack_base = (uint64_t)malloc(STACK_SIZE); + thread->user_stack_base = (uint64_t)malloc(STACK_SIZE); + thread->user_program_base = + USER_PROGRAM_BASE + thread->pid * USER_PROGRAM_SIZE; + thread->context.fp = thread->kernel_stack_base + STACK_SIZE; + thread->context.lr = (uint64_t)func; + thread->context.sp = thread->kernel_stack_base + STACK_SIZE; + for (int i = 0; i < FD_MAX; ++i) thread->fd_table.files[i] = 0; + thread->fd_table.files[0] = stdin; + thread->fd_table.files[1] = stdout; + thread->fd_table.files[2] = stderr; + run_queue_push(thread); + return thread; +} + +void schedule() { + // printf("[schdule]\n"); + if (run_queue.head == 0) { + // printf("no thread\n"); + enable_uart_interrupt(); + core_timer_disable(); + enable_interrupt(); + return; + } + if (run_queue.head == run_queue.tail) { // idle thread + // printf("left idle thread\n"); + free(run_queue.head); + run_queue.head = run_queue.tail = 0; + thread_cnt = 0; + enable_interrupt(); // need uart interrupt when go back to shell + return; + } + + do { + run_queue.tail->next = run_queue.head; + run_queue.tail = run_queue.head; + run_queue.head = run_queue.head->next; + run_queue.tail->next = 0; + } while (run_queue.head->status != THREAD_READY); + // printf("get_current()->pid = %d\n",get_current()->pid); + // printf("run_queue.head->pid = %d\n",run_queue.head->pid); + enable_interrupt(); + switch_to(get_current(), run_queue.head); +} + +void idle() { + // printf("[idle]\n"); + + while (1) { + kill_zombies(); + handle_fork(); + schedule(); + if (run_queue.head == 0) break; //blcok here if any thread exist= + } +} + +void exit() { + thread_info *cur = get_current(); + cur->status = THREAD_DEAD; + schedule(); +} + +void run_queue_push(thread_info *thread) { + if (run_queue.head == 0) { + run_queue.head = run_queue.tail = thread; + } else { + run_queue.tail->next = thread; + run_queue.tail = thread; + } +} + +void kill_zombies() { + if (run_queue.head == 0) return; + for (thread_info *ptr = run_queue.head; ptr->next != 0; ptr = ptr->next) { + for (thread_info *cur = ptr->next; + cur != 0 && (cur->status == THREAD_DEAD);) { + thread_info *tmp = cur->next; + free((void *)cur); + ptr->next = tmp; + cur = tmp; + } + if (ptr->next == 0) { + run_queue.tail = ptr; + break; + } + } +} + +void exec(const char *program_name, const char **argv) { + thread_info *cur = get_current(); + + uint64_t user_sp = cur->user_stack_base + STACK_SIZE; + cur->user_program_size = cpio_load_user_program(program_name, cur->user_program_base); + // printf("cur->pid = %d, cur->user_program_base = %x\n",cur->pid,cur->user_program_base); + + // return to user program + uint64_t spsr_el1 = 0x0; // EL0t with interrupt enabled + uint64_t target_addr = cur->user_program_base; + uint64_t target_sp = user_sp; + core_timer_enable(); + asm volatile("msr spsr_el1, %0" : : "r"(spsr_el1)); + asm volatile("msr elr_el1, %0" : : "r"(target_addr)); + asm volatile("msr sp_el0, %0" : : "r"(target_sp)); + asm volatile("eret"); +} + +void fork(uint64_t sp) { + run_queue.head->status = THREAD_FORK; + run_queue.head->trap_frame_addr = sp; + schedule(); + trap_frame_t *trap_frame = (trap_frame_t *)(get_current()->trap_frame_addr); + trap_frame->x[0] = run_queue.head->child_pid; +} + +void handle_fork() { + // printf("[handle_fork]\n"); + for (thread_info *ptr = run_queue.head->next; ptr != 0; ptr = ptr->next) { + if ((ptr->status) == THREAD_FORK) { + thread_info *child = thread_create(0); + create_child(ptr, child); + ptr->status = THREAD_READY; + child->status = THREAD_READY; + } + } +} + +void create_child(thread_info *parent, thread_info *child) { + // printf("[create_child]\n"); + disable_interrupt(); + child->user_stack_base = (uint64_t)malloc(STACK_SIZE); + child->user_program_size = parent->user_program_size; + parent->child_pid = child->pid; + child->child_pid = 0; + + char *src, *dst; + // copy saved context in thread info + src = (char *)&(parent->context); + dst = (char *)&(child->context); + for (uint32_t i = 0; i < sizeof(cpu_context); ++i, ++src, ++dst) { + *dst = *src; + } + // copy kernel stack + src = (char *)(parent->kernel_stack_base); + dst = (char *)(child->kernel_stack_base); + for (uint32_t i = 0; i < STACK_SIZE; ++i, ++src, ++dst) { + *dst = *src; + } + // copy user stack + src = (char *)(parent->user_stack_base); + dst = (char *)(child->user_stack_base); + for (uint32_t i = 0; i < STACK_SIZE; ++i, ++src, ++dst) { + *dst = *src; + } + // copy user program + src = (char *)(parent->user_program_base); + dst = (char *)(child->user_program_base); + for (uint32_t i = 0; i < parent->user_program_size; ++i, ++src, ++dst) { + *dst = *src; + } + + // set correct address for child + uint64_t kernel_stack_base_dist = + child->kernel_stack_base - parent->kernel_stack_base; + uint64_t user_stack_base_dist = + child->user_stack_base - parent->user_stack_base; + uint64_t user_program_base_dist = + child->user_program_base - parent->user_program_base; + + child->context.fp += kernel_stack_base_dist; + child->context.sp += kernel_stack_base_dist; + child->trap_frame_addr = parent->trap_frame_addr + kernel_stack_base_dist; + trap_frame_t *trap_frame = (trap_frame_t *)(child->trap_frame_addr); + trap_frame->x[29] += user_stack_base_dist; // fp (x29) + trap_frame->x[30] += user_program_base_dist; // lr (x30) + trap_frame->x[32] += user_program_base_dist; // elr_el1 + trap_frame->x[33] += user_stack_base_dist; // sp_el0 + enable_interrupt(); +} +void kill (int kill_pid) +{ + if (run_queue.head == 0) return; + for (thread_info *ptr = run_queue.head; ptr->next != 0; ptr = ptr->next) { + if(ptr->pid == kill_pid){ + printf("Kill pid = %d\n",kill_pid); + ptr->status = THREAD_DEAD; + schedule(); + return; + } + } + printf("pid = %d not exist\n",kill_pid); + +} + +struct file *thread_get_file(int fd) { + thread_info *cur = get_current(); + return cur->fd_table.files[fd]; +} + +int thread_register_fd(struct file *file) { + if (file == 0) return -1; + thread_info *cur = get_current(); + // find next available fd + for (int fd = 3; fd < FD_MAX; ++fd) { + if (cur->fd_table.files[fd] == 0) { + cur->fd_table.files[fd] = file; + return fd; + } + } + return -1; +} + +int thread_clear_fd(int fd) { + if (fd < 0 || fd >= FD_MAX) return -1; + thread_info *cur = get_current(); + cur->fd_table.files[fd] = 0; + return 1; +} \ No newline at end of file diff --git a/lab7/kernel/src/timer.c b/lab7/kernel/src/timer.c new file mode 100644 index 000000000..02095c58d --- /dev/null +++ b/lab7/kernel/src/timer.c @@ -0,0 +1,146 @@ +#include "timer.h" +#include "alloc.h" +#include "uart.h" +#include "utils.h" +#include "thread.h" + +void timeout_event_init() { + timeout_queue_head = 0; + timeout_queue_tail = 0; +} + +void core_timer_enable() { + asm volatile("mov x0, 1"); + asm volatile("msr cntp_ctl_el0, x0"); // enable + asm volatile("mrs x0, cntfrq_el0"); + asm volatile("msr cntp_tval_el0, x0"); // set expired time + asm volatile("mov x0, 2"); + asm volatile("ldr x1, =0x40000040"); + asm volatile("str w0, [x1]"); // unmask timer interrupt + + uint64_t tmp; + asm volatile("mrs %0, cntkctl_el1" : "=r"(tmp)); + tmp |= 1; + asm volatile("msr cntkctl_el1, %0" : : "r"(tmp)); +} + +// void core_timer_handler() { +// uart_puts("===== timer handler =====\n"); +// uint64_t cntpct_el0, cntfrq_el0; +// asm volatile("mrs %0, cntpct_el0" : "=r"(cntpct_el0)); +// asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq_el0)); +// asm volatile("mrs x0, cntfrq_el0"); +// asm volatile("mov x1, 2"); +// asm volatile("mul x0, x0, x1"); +// asm volatile("msr cntp_tval_el0, x0"); +// uart_puts("Time elapsed after booting: "); +// // char c = cntpct_el0 / cntfrq_el0; +// uart_int(cntpct_el0 / cntfrq_el0); +// uart_puts("s\n"); +// } + +void core_timer_disable() { + asm volatile("mov x0, 0"); + asm volatile("msr cntp_ctl_el0, x0"); // disable + asm volatile("mov x0, 0"); + asm volatile("ldr x1, =0x40000040"); + asm volatile("str w0, [x1]"); // unmask timer interrupt +} + +void core_timer_handler_lowerEL_64() { // required 2 + set_expired_time(1); + // uart_puts("Time elapsed after booting: "); + // uart_int(get_current_time()); + // uart_puts("s\n"); + schedule(); +} + +void core_timer_handler_currentEL_ELx() { // elective 2 + uart_puts("Current time: "); + uart_int(get_current_time()); + uart_puts("s, "); + uart_puts("Command executed time: "); + uart_int(timeout_queue_head->register_time); + uart_puts("s, "); + uart_puts("Duration: "); + uart_int(timeout_queue_head->duration); + uart_puts("s\n"); + timeout_queue_head->callback(timeout_queue_head->args); + timeout_event *next = timeout_queue_head->next; + // free(timeout_queue_head); + if (next) { + next->prev = 0; + timeout_queue_head = next; + uint64_t next_duration = + next->register_time + next->duration - get_current_time(); + set_expired_time(next_duration); + } else { + timeout_queue_head = 0; + timeout_queue_tail = 0; + core_timer_disable(); + } +} + +void add_timer(void (*callback)(char *), char *args, uint32_t duration) { + timeout_event *new_timeout_event = + (timeout_event *)malloc(sizeof(timeout_event)); + new_timeout_event->register_time = get_current_time(); + new_timeout_event->duration = duration; + new_timeout_event->callback = callback; + for (int i = 0; i < 20; i++) { + new_timeout_event->args[i] = args[i]; + if (args[i] == '\0') break; + } + new_timeout_event->prev = 0; + new_timeout_event->next = 0; + + if (timeout_queue_head == 0) { + timeout_queue_head = new_timeout_event; + timeout_queue_tail = new_timeout_event; + core_timer_enable(); + set_expired_time(duration); + } else { + timeout_event *cur; + uint64_t timeout = + new_timeout_event->register_time + new_timeout_event->duration; + for (cur = timeout_queue_head; cur; cur = cur->next) { + if (cur->register_time + cur->duration > timeout) break; + } + + if (cur == 0) { + new_timeout_event->prev = timeout_queue_tail; + timeout_queue_tail->next = new_timeout_event; + timeout_queue_tail = new_timeout_event; + } else if (cur->prev == 0) { + new_timeout_event->next = cur; + timeout_queue_head->prev = new_timeout_event; + timeout_queue_head = new_timeout_event; + set_expired_time(duration); + } else { + new_timeout_event->prev = cur->prev; + new_timeout_event->next = cur; + cur->prev->next = new_timeout_event; + cur->prev = new_timeout_event; + } + } +} + +uint64_t get_current_time() { + uint64_t cntpct_el0, cntfrq_el0; + asm volatile("mrs %0, cntpct_el0" : "=r"(cntpct_el0)); + asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq_el0)); + return cntpct_el0 / cntfrq_el0; +} + + +void set_expired_time(uint32_t duration) { + uint64_t cntfrq_el0; + asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq_el0)); + asm volatile("msr cntp_tval_el0, %0" : : "r"(cntfrq_el0 * duration / 32)); +} + +void timer_callback(char *msg) { + uart_puts("Message: "); + uart_puts(msg); + uart_puts("\n"); +} \ No newline at end of file diff --git a/lab7/kernel/src/tmpfs.c b/lab7/kernel/src/tmpfs.c new file mode 100644 index 000000000..4a066b445 --- /dev/null +++ b/lab7/kernel/src/tmpfs.c @@ -0,0 +1,142 @@ +#include "tmpfs.h" + +#include "alloc.h" +#include "printf.h" +#include "string.h" +#include "vfs.h" + +void tmpfs_init() { + tmpfs_v_ops = + (struct vnode_operations*)malloc(sizeof(struct vnode_operations)); + tmpfs_v_ops->lookup = tmpfs_lookup; + tmpfs_v_ops->create = tmpfs_create; + tmpfs_v_ops->set_parent = tmpfs_set_parent; + tmpfs_f_ops = (struct file_operations*)malloc(sizeof(struct file_operations)); + tmpfs_f_ops->write = tmpfs_write; + tmpfs_f_ops->read = tmpfs_read; + tmpfs_f_ops->list = tmpfs_list; +} + +void tmpfs_set_fentry(struct tmpfs_fentry* fentry, const char* component_name, + FILE_TYPE type, struct vnode* vnode) { + strcpy(fentry->name, component_name); + fentry->vnode = vnode; + fentry->type = type; + fentry->buf = (struct tmpfs_buf*)malloc(sizeof(struct tmpfs_buf)); + for (int i = 0; i < TMPFS_BUF_SIZE; i++) { + fentry->buf->buffer[i] = '\0'; + } + + if (fentry->type == FILE_DIRECTORY) { + for (int i = 0; i < MAX_FILES_IN_DIR; ++i) { + fentry->child[i] = + (struct tmpfs_fentry*)malloc(sizeof(struct tmpfs_fentry)); + fentry->child[i]->name[0] = 0; + fentry->child[i]->type = FILE_NONE; + fentry->child[i]->parent_vnode = vnode; + } + fentry->buf->size = TMPFS_BUF_SIZE; + } else if (fentry->type == FILE_REGULAR) { + fentry->buf->size = 0; + } +} + +int tmpfs_setup_mount(struct filesystem* fs, struct mount* mount) { + struct tmpfs_fentry* root_fentry = + (struct tmpfs_fentry*)malloc(sizeof(struct tmpfs_fentry)); + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = mount; + vnode->v_ops = tmpfs_v_ops; + vnode->f_ops = tmpfs_f_ops; + vnode->internal = (void*)root_fentry; + root_fentry->parent_vnode = 0; + tmpfs_set_fentry(root_fentry, "/", FILE_DIRECTORY, vnode); + mount->fs = fs; + mount->root = vnode; + return 1; +} + +int tmpfs_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name) { + // printf("[lookup] %s\n", component_name); + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)dir_node->internal; + if (fentry->type != FILE_DIRECTORY) return 0; + + if (!strcmp(component_name, ".")) { + *target = fentry->vnode; + return 1; + } + if (!strcmp(component_name, "..")) { + if (!fentry->parent_vnode) return 0; + *target = fentry->parent_vnode; + return 1; + } + + for (int i = 0; i < MAX_FILES_IN_DIR; i++) { + fentry = ((struct tmpfs_fentry*)dir_node->internal)->child[i]; + if (!strcmp(fentry->name, component_name)) { + *target = fentry->vnode; + return 1; + } + } + return 0; +} + +int tmpfs_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type) { + for (int i = 0; i < MAX_FILES_IN_DIR; i++) { + struct tmpfs_fentry* fentry = + ((struct tmpfs_fentry*)dir_node->internal)->child[i]; + if (fentry->type == FILE_NONE) { + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = 0; + vnode->v_ops = dir_node->v_ops; + vnode->f_ops = dir_node->f_ops; + vnode->internal = fentry; + tmpfs_set_fentry(fentry, component_name, type, vnode); + *target = fentry->vnode; + return 1; + } + } + return -1; +} + +int tmpfs_set_parent(struct vnode* child_node, struct vnode* parent_vnode) { + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)child_node->internal; + fentry->parent_vnode = parent_vnode; + return 1; +} + +int tmpfs_write(struct file* file, const void* buf, size_t len) { + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)file->vnode->internal; + for (size_t i = 0; i < len; i++) { + fentry->buf->buffer[file->f_pos++] = ((char*)buf)[i]; + if (fentry->buf->size < file->f_pos) { + fentry->buf->size = file->f_pos; + } + } + return len; +} + +int tmpfs_read(struct file* file, void* buf, size_t len) { + size_t read_len = 0; + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)file->vnode->internal; + for (size_t i = 0; i < len; i++) { + ((char*)buf)[i] = fentry->buf->buffer[file->f_pos++]; + read_len++; + if (read_len == fentry->buf->size) { + break; + } + } + return read_len; +} + +int tmpfs_list(struct file* file, void* buf, int index) { + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)file->vnode->internal; + if (fentry->type != FILE_DIRECTORY) return -1; + if (index >= MAX_FILES_IN_DIR) return -1; + + if (fentry->child[index]->type == FILE_NONE) return 0; + strcpy((char*)buf, fentry->child[index]->name); + return fentry->child[index]->buf->size; +} \ No newline at end of file diff --git a/lab7/kernel/src/uart.c b/lab7/kernel/src/uart.c new file mode 100644 index 000000000..44d542e1f --- /dev/null +++ b/lab7/kernel/src/uart.c @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" +#include "utils.h" +#include "uart.h" +#include "vfs.h" + +/* Auxilary mini UART registers */ +#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004)) +#define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE+0x00215040)) +#define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE+0x00215044)) +#define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE+0x00215048)) +#define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE+0x0021504C)) +#define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE+0x00215050)) +#define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE+0x00215054)) +#define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE+0x00215058)) +#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE+0x0021505C)) +#define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE+0x00215060)) +#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064)) +#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068)) +/** + * Set baud rate and characteristics (115200 8N1) and map to GPIO + */ +void uart_init() +{ + register unsigned int r; + + /* initialize UART */ + *AUX_ENABLE |=1; // enable UART1, AUX mini uart + *AUX_MU_CNTL = 0; + *AUX_MU_LCR = 3; // 8 bits + *AUX_MU_MCR = 0; + *AUX_MU_IER = 1; + // comment this line to avoid weird character + // *AUX_MU_IIR = 0xc6; // disable interrupts + *AUX_MU_BAUD = 270; // 115200 baud + /* map UART1 to GPIO pins */ + r=*GPFSEL1; + r&=~((7<<12)|(7<<15)); // gpio14, gpio15 + r|=(2<<12)|(2<<15); // alt5 + *GPFSEL1 = r; + *GPPUD = 0; // enable pins 14 and 15 + r=150; while(r--) { asm volatile("nop"); } + *GPPUDCLK0 = (1<<14)|(1<<15); + r=150; while(r--) { asm volatile("nop"); } + *GPPUDCLK0 = 0; // flush GPIO setup + *AUX_MU_CNTL = 3; // enable Tx, Rx + + read_buf_start = read_buf_end = 0; + write_buf_start = write_buf_end = 0; + enable_uart_interrupt(); +} + +/** + * Send a character + */ +void uart_send(unsigned int c) { + /* wait until we can send */ + do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x20)); + /* write the character to the buffer */ + *AUX_MU_IO=c; +} + +/** + * Receive a character + */ +char uart_getc() { + char r; + /* wait until something is in the buffer */ + do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01)); + /* read it and return */ + r=(char)(*AUX_MU_IO); + /* convert carrige return to newline */ + return r=='\r'?'\n':r; +} + +uint32_t uart_gets(char *buf, uint32_t size) { + for (int i = 0; i < size; ++i) { + buf[i] = uart_getc(); + // uart_send(buf[i]); + if (buf[i] == '\n' || buf[i] == '\r') { + // uart_send('\r'); + // buf[i] = '\0'; + return i; + } + } + return size; +} + +/** + * Display a string + */ +void uart_puts(char *s) { + while(*s) { + /* convert newline to carrige return + newline */ + if(*s=='\n') + uart_send('\r'); + uart_send(*s++); + } +} + +uint32_t uart_write(char *s, uint32_t size) { + for(int i = 0 ; i=0;c-=4) { + // get highest tetrad + n=(d>>c)&0xF; + // 0-9 => '0'-'9', 10-15 => 'A'-'F' + n+=n>9?0x37:0x30; + uart_send(n); + } +} + +void uart_int(int x) { + if (x < 0) { + uart_send('-'); + x = -x; + } + if (x >= 10) uart_int(x / 10); + uart_send(x % 10 + '0'); +} + +void enable_uart_interrupt() { *ENABLE_IRQS_1 = AUX_IRQ; } + +void disable_uart_interrupt() { *DISABLE_IRQS_1 = AUX_IRQ; } + +void assert_transmit_interrupt() { *AUX_MU_IER |= 0x2; } + +void clear_transmit_interrupt() { *AUX_MU_IER &= ~(0x2); } + +void uart_handler() { + disable_uart_interrupt(); + int is_read = (*AUX_MU_IIR & 0x4); + int is_write = (*AUX_MU_IIR & 0x2); + + if (is_read) { + // uart_puts("===== is_read =====\n"); + + char c = (char)(*AUX_MU_IO); + read_buf[read_buf_end++] = c; + if (read_buf_end == UART_BUFFER_SIZE) read_buf_end = 0; + } else if (is_write) { + // uart_puts("===== is_write =====\n"); + + while (*AUX_MU_LSR & 0x20) { + if (write_buf_start == write_buf_end) { + clear_transmit_interrupt(); + break; + } + char c = write_buf[write_buf_start++]; + *AUX_MU_IO = c; + if (write_buf_start == UART_BUFFER_SIZE) write_buf_start = 0; + } + } + enable_uart_interrupt(); +} + +char uart_async_getc() { + // wait until there are new data + // uart_puts("===== uart getc =====\n"); + while (read_buf_start == read_buf_end) { + // uart_puts("===== read_buf_start == read_buf_end =====\n"); + asm volatile("nop"); + } + char c = read_buf[read_buf_start++]; + if (read_buf_start == UART_BUFFER_SIZE) read_buf_start = 0; + // '\r' => '\n' + return c == '\r' ? '\n' : c; +} + +void uart_async_puts(char *str) { + for (int i = 0; str[i]; i++) { + if (str[i] == '\n') write_buf[write_buf_end++] = '\r'; + write_buf[write_buf_end++] = str[i]; + if (write_buf_end == UART_BUFFER_SIZE) write_buf_end = 0; + } + assert_transmit_interrupt(); +} diff --git a/lab7/kernel/src/utils.S b/lab7/kernel/src/utils.S new file mode 100644 index 000000000..894a1fdc8 --- /dev/null +++ b/lab7/kernel/src/utils.S @@ -0,0 +1,9 @@ +.globl put32 +put32: + str w1, [x0] + ret + +.globl get32 +get32: + ldr w0, [x0] + ret diff --git a/lab7/kernel/src/utils.c b/lab7/kernel/src/utils.c new file mode 100644 index 000000000..8047ee2c7 --- /dev/null +++ b/lab7/kernel/src/utils.c @@ -0,0 +1,71 @@ +// typedef unsigned long long int uint64_t; +// typedef unsigned char uint8_t; +#include "utils.h" + +uint8_t hex_to_int8(char hex){ + if(hex >= '0' && hex <= '9') + return hex-'0'; + else if(hex >= 'A' && hex <= 'Z') + return hex-'A'+10; + else if(hex >= 'a' && hex <= 'z') + return hex-'a'+10; + else + return -1; +} + +uint64_t hex_to_int64(char* num){ + uint64_t res=0; + for(int i=0; i<8; i++){ + res = (res<<4) + hex_to_int8(num[i]); + } + return res; +} + +uint64_t log2(uint64_t num) { + for (uint64_t i = 0; i < 64; i++) { + if (num == (1 << i)) return i; + } + return 0; +} +uint64_t align_up(uint64_t addr, uint64_t alignment) { + return (addr + alignment - 1) & (~(alignment - 1)); +} + +uint64_t align_up_exp(uint64_t n) { + n--; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n |= n >> 32; + n++; + return n; +} + +void delay(int num) { + while (num--) + ; +} + +uint64_t hex2int(char *hex, int len) { + uint64_t val = 0; + for (int i = 0; i < len; i++) { + // get current character then increment + uint64_t byte = *(hex + i); + if (byte >= '0' && byte <= '9') + byte = byte - '0'; + else if (byte >= 'A' && byte <= 'F') + byte = byte - 'A' + 10; + else if (byte >= 'a' && byte <= 'f') + byte = byte - 'a' + 10; + + val = (val << 4) | (byte & 0xF); + } + return val; +} + +uint32_t be2le(uint32_t x) { + return (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) | + (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); +} \ No newline at end of file diff --git a/lab7/kernel/src/vfs.c b/lab7/kernel/src/vfs.c new file mode 100644 index 000000000..9c66b3164 --- /dev/null +++ b/lab7/kernel/src/vfs.c @@ -0,0 +1,346 @@ +#include "vfs.h" + +#include "alloc.h" +#include "cpio.h" +// #include "fatfs.h" +#include "printf.h" +#include "string.h" +#include "thread.h" +#include "tmpfs.h" +#include "device.h" + +void vfs_test() { + const char* argv[] = {"vfs_test", 0}; + exec("vfs_test", argv); +} + +void vfs_ls_test() { + const char* argv[] = {"ls", ".", 0}; + exec("ls", argv); +} + +void vfs_hard_test() { + const char* argv[] = {"vfs_test_hard", 0}; + exec("vfs_test_hard", argv); +} + +void vfs_fat_test() { + const char* argv[] = {"fatfs_test", 0}; + exec("fatfs_test", argv); +} + +void vnode_print( struct vnode* vnode){ + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*) vnode->internal; + printf("[vnode_print]name = %s\n", fentry->name); +} + +void vfs_init() { + fs_list.head = 0; + fs_list.tail = 0; + // init and register tmpfs + tmpfs_init(); + struct filesystem* tmpfs = + (struct filesystem*)malloc(sizeof(struct filesystem)); + tmpfs->name = "tmpfs"; + tmpfs->setup_mount = tmpfs_setup_mount; + register_filesystem(tmpfs); + + // use tmpfs to mount root filesystem + rootfs = (struct mount*)malloc(sizeof(struct mount)); + struct filesystem* fs = get_fs_by_name("tmpfs"); + if (fs == 0) { + // printf("[Error] Mount root filesystem failed!!\n"); + return; + } + fs->setup_mount(fs, rootfs); + current_dir = rootfs->root; + // cpio_populate_rootfs(); + + // init and register cpio + cpiofs_init(); + struct filesystem* cpiofs = + (struct filesystem*)malloc(sizeof(struct filesystem)); + cpiofs->name = "cpiofs"; + cpiofs->setup_mount = cpiofs_setup_mount; + register_filesystem(cpiofs); + + //iniframfs + vfs_mkdir("/initramfs"); + vfs_mount("", "/initramfs", "cpiofs"); + + //device + device_init(); + struct filesystem* devfs = + (struct filesystem*)malloc(sizeof(struct filesystem)); + devfs->name = "dev"; + devfs->setup_mount = device_setup_mount; + register_filesystem(devfs); + + vfs_mkdir("/dev"); + vfs_mount("", "/dev", "dev"); + // uart + stdin = vfs_open("/dev/uart", 0); + stdout = vfs_open("/dev/uart", 0); + stderr = vfs_open("/dev/uart", 0); +} + +int register_filesystem(struct filesystem* fs) { + // register the file system to the kernel. + if (fs_list.head == 0) { + fs_list.head = fs; + fs_list.head->next = 0; + fs_list.tail = fs_list.head; + } else { + fs_list.tail->next = fs; + fs_list.tail = fs_list.tail->next; + } + return 1; +} + +struct filesystem* get_fs_by_name(const char* name) { + for (struct filesystem* fs = fs_list.head; fs != 0; fs = fs->next) { + if (!strcmp(fs->name, name)) { + return fs; + } + } + // printf("[Error] Filesystem \'%s\' not found!!\n", name); + return 0; +} + +int vfs_find_vnode(struct vnode** target, const char* pathname) { + if (!strcmp(pathname, "/")) { + *target = rootfs->root; + return 1; + } + + char* pathname_ = (char*)malloc(strlen(pathname) + 1); + strcpy(pathname_, pathname); + struct vnode* dir = current_dir; + if (pathname_[0] == '/') dir = rootfs->root; + // printf("[vfs_find_vnode]find node: %s\n", pathname_); + + char* component_name = strtok(pathname_, '/'); + while (component_name && *component_name != '\0') { + int found = dir->v_ops->lookup(dir, target, component_name); + // printf("[vfs_find_vnode]component name: %s, found %d\n", component_name, found); + if (!found) { + printf("[Error] No such file or directory: %s\n", pathname); + free(pathname_); + return 0; + } + if ((*target)->mount) *target = (*target)->mount->root; + dir = *target; + component_name = strtok(0, '/'); + } + free(pathname_); + return 1; +} + +struct file* vfs_open(const char* pathname, int flags) { + // 1. Lookup pathname from the root vnode. + // 2. Create a new file descriptor for this vnode if found. + // 3. Create a new file if O_CREAT is specified in flags. + struct vnode* dir = current_dir; + struct vnode* target = 0; + struct file* file = 0; + + char* pathname_ = (char*)malloc(strlen(pathname) + 1); + strcpy(pathname_, pathname); + // pathname: /mnt -> pathname_: "\0", filename: mnt + // pathname: /mnt/file1 -> pathname_: /mnt, filename: file1 + // pathname: file1 -> pathname_: file1, filename: NULL + char* filename = split_last(pathname_, '/'); + // printf("[vfs_open] pathname_ :%s, filename :%s\n", pathname_, filename); + if (*pathname_ == '\0' && pathname[0] == '/') { + dir = rootfs->root; + } + if (filename != 0) { + int prefix_found = vfs_find_vnode(&dir, pathname_); + // e.g., given pathname /abc/zxc/file1, but /abc/zxc not found + if (!prefix_found) { + printf("[Error] Path does not exist: %s\n", pathname); + free(pathname_); + return 0; + } + } else { + filename = pathname_; + } + + int file_found = dir->v_ops->lookup(dir, &target, filename); + if (flags == O_CREAT) { + printf("[open]CREATE\n"); + if (!file_found) { + dir->v_ops->create(dir, &target, filename, FILE_REGULAR); + file = (struct file*)malloc(sizeof(struct file)); + file->vnode = target; + file->f_ops = target->f_ops; + file->f_pos = 0; + } else { + printf("[Error] File already exists: %s\n", pathname); + } + } else { + if (!file_found) { + printf("[Error] File does not exist: %s\n", pathname); + } else { + if (target->mount) target = target->mount->root; + file = (struct file*)malloc(sizeof(struct file)); + file->vnode = target; + file->f_ops = target->f_ops; + file->f_pos = 0; + } + } + free(pathname_); + return file; +} + +int vfs_close(struct file* file) { + // 1. release the file descriptor + // free(file); + return 1; +} + +int vfs_write(struct file* file, const void* buf, size_t len) { + // 1. write len byte from buf to the opened file. + // 2. return written size or error code if an error occurs. + return file->f_ops->write(file, buf, len); +} + +int vfs_read(struct file* file, void* buf, size_t len) { + // 1. read min(len, readable file data size) byte to buf from the opened file. + // 2. return read size or error code if an error occurs. + return file->f_ops->read(file, buf, len); +} + +int vfs_list(struct file* file, void* buf, int index) { + return file->f_ops->list(file, buf, index); +} + +int vfs_mkdir(const char* pathname) { + // printf("%s\n", pathname); + struct vnode* dir = current_dir; + struct vnode* target = 0; + + char* pathname_ = (char*)malloc(strlen(pathname) + 1); + strcpy(pathname_, pathname); + // pathname: /mnt -> pathname_: "\0", dirname: mnt + // pathname: /mnt/dir1 -> pathname_: /mnt, dirname: dir1 + // pathname: dir1 -> pathname_: dir1, dirname: NULL + char* dirname = split_last(pathname_, '/'); + printf("[vfs_mkdir] pathname_ :%s, dirname :%s\n", pathname_, dirname); + + if (*pathname_ == '\0' && pathname[0] == '/') { + dir = rootfs->root; + } + + if (dirname != 0) { + int prefix_found = vfs_find_vnode(&dir, pathname_); + // e.g., given pathname /abc/zxc/file1, but /abc/zxc not found + if (!prefix_found) { + // printf("[Error] Path does not exist: %s\n", pathname); + free(pathname_); + return 0; + } + } else { + dirname = pathname_; + } + + int file_found = dir->v_ops->lookup(dir, &target, dirname); + if (file_found) { + printf("[Error] File already exists: %s\n", pathname); + return 0; + } + int status = dir->v_ops->create(dir, &target, dirname, FILE_DIRECTORY); + free(pathname_); + return status; +} + +int vfs_chdir(const char* pathname) { + struct vnode* target = 0; + int dir_found = vfs_find_vnode(&target, pathname); + if (!dir_found) { + // printf("[Error] Directory does not exist: %s\n", pathname); + return 0; + } + vnode_print(current_dir); + vnode_print(target); + current_dir = target; + // struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)current_dir->internal; + // printf("[chdir] %s\n", fentry->name); + return 1; +} + +int vfs_mount(const char* device, const char* mountpoint, + const char* filesystem) { + printf("[vfs_mount] %s\n", mountpoint); + struct vnode* target = 0; + int dir_found = vfs_find_vnode(&target, mountpoint); + + if (!dir_found) { + printf("[Error] Directory does not exist: %s\n", mountpoint); + return 0; + } + if (target->mount) { + printf("[Error] This directory has been mounted: %s\n", mountpoint); + return 0; + } + + // find parent_vnode + char* pathname_ = (char*)malloc(strlen(mountpoint) + 5); + strcpy(pathname_, mountpoint); + struct vnode* parent_vnode = 0; + strcat(pathname_, "/.."); + // int parent_found = vfs_find_vnode(&parent_vnode, pathname_); + vfs_find_vnode(&parent_vnode, pathname_); + free(pathname_); + + struct mount* mountfs = (struct mount*)malloc(sizeof(struct mount)); + struct filesystem* fs = get_fs_by_name(filesystem); + fs->setup_mount(fs, mountfs); + + //target is mountpoint + target->mount = mountfs; + mountfs->root->v_ops->set_parent(mountfs->root, parent_vnode); + return 1; +} + +int vfs_umount(const char* mountpoint) { + // printf("[umount] %s\n", mountpoint); + struct vnode* dir = current_dir; + struct vnode* target = 0; + + char* pathname_ = (char*)malloc(strlen(mountpoint) + 1); + strcpy(pathname_, mountpoint); + // pathname: /mnt -> pathname_: "\0", dirname: mnt + // pathname: /mnt/dir1 -> pathname_: /mnt, dirname: dir1 + // pathname: dir1 -> pathname_: dir1, dirname: NULL + char* dirname = split_last(pathname_, '/'); + if (*pathname_ == '\0' && mountpoint[0] == '/') { + dir = rootfs->root; + } + // printf("%s %s\n", pathname_, dirname); + + if (dirname != 0) { + int prefix_found = vfs_find_vnode(&dir, pathname_); + // e.g., given pathname /abc/zxc/file1, but /abc/zxc not found + if (!prefix_found) { + // printf("[Error] Path does not exist: %s\n", mountpoint); + free(pathname_); + return 0; + } + } else { + dirname = pathname_; + } + + int file_found = dir->v_ops->lookup(dir, &target, dirname); + if (!file_found) { + // printf("[Error] Directory does not exist: %s\n", mountpoint); + return 0; + } + + if (!target->mount) { + // printf("[Error] This directory is not mounted: %s\n", mountpoint); + return 0; + } + target->mount = 0; + return 1; +} \ No newline at end of file diff --git a/lab7/make.sh b/lab7/make.sh new file mode 100755 index 000000000..893cdd3e6 --- /dev/null +++ b/lab7/make.sh @@ -0,0 +1,9 @@ +#bin/sh! + +make +cd kernel +make +cd .. +cd bootloader +make +cd .. diff --git a/lab7/qemu_run.sh b/lab7/qemu_run.sh new file mode 100755 index 000000000..4673212bd --- /dev/null +++ b/lab7/qemu_run.sh @@ -0,0 +1,4 @@ +# sudo chmod 777 /dev/ttyUSB0 +# python3 ./script/send_file.py -s bootloader.img +# python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/ttyUSB0 +python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/pts/14 diff --git a/lab7/run.sh b/lab7/run.sh new file mode 100755 index 000000000..a8d89f256 --- /dev/null +++ b/lab7/run.sh @@ -0,0 +1,4 @@ +sudo chmod 777 /dev/ttyUSB0 +# python3 ./script/send_file.py -s bootloader.img +python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/ttyUSB0 +# python3 ./script/send_file.py -s kernel8.img -t /dev/pts/9 diff --git a/lab7/script/send_file.py b/lab7/script/send_file.py new file mode 100644 index 000000000..475fab1ec --- /dev/null +++ b/lab7/script/send_file.py @@ -0,0 +1,42 @@ +import argparse +from pathlib import Path +import serial + +def send_all_data(tty, data): + while len(data) > 0: + write_cnt = tty.write(data) + data = data[write_cnt:] + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + "-s", + "--src_file_pth", + type=str, + help='source file path', + default='../kernel8.img' + ) + parser.add_argument( + "-t", + "--target_pth", + nargs='?', + type=str, + help='target path', + default='/dev/ttyUSB0' + ) + args = parser.parse_args() + + with serial.Serial(args.target_pth, 115200, xonxoff=True) as tty: + magic = 0x01020304.to_bytes(4, 'big') + send_all_data(tty, magic) + + file_size = Path(args.src_file_pth).stat().st_size.to_bytes(8, 'little') + send_all_data(tty, file_size) + + with open(args.src_file_pth, 'rb') as src_file: + while True: + data = src_file.read() + if data == b'': + break + send_all_data(tty, data) + print("finish sending kernel8.img\n") \ No newline at end of file diff --git a/lab7/user/Makefile b/lab7/user/Makefile new file mode 100644 index 000000000..8961cfcb5 --- /dev/null +++ b/lab7/user/Makefile @@ -0,0 +1,32 @@ +CC = aarch64-linux-gnu-gcc +CFLAGS = -Wall -g -ffreestanding -march=armv8-a +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJCOPYFLAGS = -O binary + +BUILD_DIR = build +SRC_DIR = src +C_FILES = $(wildcard $(SRC_DIR)/*.c) +TARGET_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%) +LINKER = $(SRC_DIR)/linker.ld + +all: $(TARGET_FILES) + +clean: + rm $(BUILD_DIR)/* + +$(BUILD_DIR)/%: $(BUILD_DIR)/%.elf + $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ + cp $@ ../kernel/rootfs && \ + cd ../kernel/rootfs && \ + rm -f ../initramfs.cpio && \ + find . | cpio -o -H newc > ../initramfs.cpio + +$(BUILD_DIR)/%.elf: $(BUILD_DIR)/%.o $(BUILD_DIR)/start.asmo + $(LD) -T $(LINKER) --gc-sections -g -o $@ $< $(BUILD_DIR)/start.asmo + +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/start.asmo: $(SRC_DIR)/start.S + $(CC) $(CFLAGS) -c $< -o $@ diff --git a/lab7/user/src/argv_test.c b/lab7/user/src/argv_test.c new file mode 100644 index 000000000..aa9c5bed3 --- /dev/null +++ b/lab7/user/src/argv_test.c @@ -0,0 +1,17 @@ +#include "start.h" + +int main(int argc, char **argv) { + // printf("Argv Test, pid %d\n", getpid()); + print_s("Argv Test, pid "); + print_i(getpid()); + print_s("\n"); + for (int i = 0; i < argc; ++i) { + // puts(argv[i]); + print_s(argv[i]); + print_s("\n"); + } + char *fork_argv[] = {"fork_test", 0}; + exec("fork_test", fork_argv); + + return 0; +} \ No newline at end of file diff --git a/lab7/user/src/fork_test.c b/lab7/user/src/fork_test.c new file mode 100644 index 000000000..a8b65a079 --- /dev/null +++ b/lab7/user/src/fork_test.c @@ -0,0 +1,46 @@ +#include "start.h" + +int main() { + // printf("Fork Test, pid %d\n", getpid()); + print_s("Fork Test, pid "); + print_i(getpid()); + print_s("\n"); + int cnt = 1; + int ret = 0; + if ((ret = fork()) == 0) { // child + // printf("pid: %d, cnt: %d, ptr: %p\n", getpid(), cnt, &cnt); + print_s("pid: "); + print_i(getpid()); + print_s(", cnt: "); + print_i(cnt); + print_s(", ptr: "); + print_h((unsigned long long)&cnt); + print_s("\n"); + ++cnt; + fork(); + while (cnt < 5) { + // printf("pid: %d, cnt: %d, ptr: %p\n", getpid(), cnt, &cnt); + print_s("pid: "); + print_i(getpid()); + print_s(", cnt: "); + print_i(cnt); + print_s(", ptr: "); + print_h((unsigned long long)&cnt); + print_s("\n"); + delay(1000000000); + ++cnt; + } + } else { + // printf("parent here, pid %d, child %d\n", getpid(), ret); + for(int i = 0 ; i < 5;i++){ + print_s("parent here, pid: "); + print_i(getpid()); + print_s(", child: "); + print_i(ret); + print_s("\n"); + delay(1000000000); + } + } + // while(1); + return 0; +} \ No newline at end of file diff --git a/lab7/user/src/linker.ld b/lab7/user/src/linker.ld new file mode 100644 index 000000000..8e6ab1c9d --- /dev/null +++ b/lab7/user/src/linker.ld @@ -0,0 +1,17 @@ +SECTIONS +{ + . = 0x80000; + + .text : { KEEP(*(.text.boot)) *(.text .text.*) } + + .rodata : { *(.rodata .rodata.*) } + + .data : { *(.data .data.*) } + + .bss : { + *(.bss .bss.*) + *(COMMON) + } + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} \ No newline at end of file diff --git a/lab7/user/src/my_test.c b/lab7/user/src/my_test.c new file mode 100644 index 000000000..ef5620ae8 --- /dev/null +++ b/lab7/user/src/my_test.c @@ -0,0 +1,12 @@ +#include "start.h" +int main(int argc, char **argv) { + for(int i = 0 ; i<10 ; i++){ + print_s("Test1, pid "); + print_i(getpid()); + print_s("\n"); + delay(1000000000); + // asm volatile("mov x8, #9"); + // asm volatile("svc 0"); + } + return 0; +} \ No newline at end of file diff --git a/lab7/user/src/my_test2.c b/lab7/user/src/my_test2.c new file mode 100644 index 000000000..8024d8bbd --- /dev/null +++ b/lab7/user/src/my_test2.c @@ -0,0 +1,12 @@ +#include "start.h" +int main(int argc, char **argv) { + for(int i = 0 ; i<10 ; i++){ + print_s("Test2, pid "); + print_i(getpid()); + print_s("\n"); + delay(1000000000); + // asm volatile("mov x8, #9"); + // asm volatile("svc 0"); + } + return 0 ; +} \ No newline at end of file diff --git a/lab7/user/src/start.S b/lab7/user/src/start.S new file mode 100644 index 000000000..fc5a50624 --- /dev/null +++ b/lab7/user/src/start.S @@ -0,0 +1,49 @@ +.section ".text.boot" + +.global _start + +_start: + bl main + b exit + +.section ".text" + +.global uart_read +.global uart_write +.global getpid +.global fork +.global exec +.global exit + +getpid: + mov x8, #0 + svc 0 + ret + +uart_read: + mov x8, #1 + svc 0 + ret + +uart_write: + mov x8, #2 + svc 0 + ret + +exec: + mov x8, #3 + svc 0 + ret + +fork: + mov x8, #4 + svc 0 + ret + +exit: + mov x8, #5 + svc 0 + ret + + + diff --git a/lab7/user/src/start.h b/lab7/user/src/start.h new file mode 100644 index 000000000..24468b7ca --- /dev/null +++ b/lab7/user/src/start.h @@ -0,0 +1,54 @@ +#ifndef START_H +#define START_H + +#include +#include + +unsigned long uart_read(char buf[], size_t size); +unsigned long uart_write(const char buf[], size_t size); +int getpid(); +unsigned long fork(); +int exec(const char *name, char *const argv[]); +void exit(); + +void delay(int n) { + while (n--) + ; +} + +int strlen(const char *s) { + int len = 0; + while (s[len] != '\0') { + len++; + } + return len; +} + +void print_c(char c) { + char s[2]; + s[0] = c; + s[1] = '\0'; + uart_write(s, strlen(s)); +} + +void print_s(char *s) { uart_write(s, strlen(s)); } + +void print_i(int x) { + if (x < 0) { + print_c('-'); + x = -x; + } + if (x >= 10) print_i(x / 10); + print_c(x % 10 + '0'); +} + +void print_h(unsigned long x) { + print_s("0x"); + for (int c = 28; c >= 0; c -= 4) { + int n = (x >> c) & 0xF; + n += n > 9 ? 'A' - 10 : '0'; + print_c(n); + } +} + +#endif \ No newline at end of file diff --git a/lab7/user/src/svc_test.c b/lab7/user/src/svc_test.c new file mode 100644 index 000000000..a3fbfe8dd --- /dev/null +++ b/lab7/user/src/svc_test.c @@ -0,0 +1,7 @@ +int main() { + for (int i = 0; i < 5; i++) { + asm volatile("svc 0"); + } + + return 0; +} \ No newline at end of file diff --git a/lab7/user/src/user_program.S b/lab7/user/src/user_program.S new file mode 100644 index 000000000..838323763 --- /dev/null +++ b/lab7/user/src/user_program.S @@ -0,0 +1,11 @@ +.section ".text" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b \ No newline at end of file diff --git a/lab8/bootloader/Makefile b/lab8/bootloader/Makefile new file mode 100644 index 000000000..cff2e3c2a --- /dev/null +++ b/lab8/bootloader/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) 2018 bzt (bztsrc@github) +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, copy, +# modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +# + +CFILE = $(wildcard *.c) +ASMFILE = $(wildcard *.S) +OBJS = $(CFILE:.c=_c.o) +OBJS += $(ASMFILE:.S=_s.o) +CFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -fno-stack-protector -Iinclude -Iinclude + +all: kernel8.img + +%_s.o: %.S + aarch64-elf-gcc $(CFLAGS) -c $< -o $@ + +%_c.o: %.c + aarch64-elf-gcc $(CFLAGS) -c $< -o $@ + +kernel8.img: $(OBJS) + aarch64-elf-ld -nostdlib -nostartfiles $(OBJS) -T link.ld -o bootloader.elf + aarch64-elf-objcopy -O binary bootloader.elf bootloader.img + +clean: + rm kernel8.elf *.o >/dev/null 2>/dev/null || true + +run: + qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial null -serial stdio diff --git a/lab8/bootloader/bootloader.elf b/lab8/bootloader/bootloader.elf new file mode 100755 index 000000000..74f2d52e7 Binary files /dev/null and b/lab8/bootloader/bootloader.elf differ diff --git a/lab8/bootloader/bootloader.img b/lab8/bootloader/bootloader.img new file mode 100755 index 000000000..e777a0053 Binary files /dev/null and b/lab8/bootloader/bootloader.img differ diff --git a/lab8/bootloader/include/mini_uart.h b/lab8/bootloader/include/mini_uart.h new file mode 100644 index 000000000..aebc2c5a2 --- /dev/null +++ b/lab8/bootloader/include/mini_uart.h @@ -0,0 +1,9 @@ +#ifndef _MINI_UART_H +#define _MINI_UART_H + +void uart_init(void); +char uart_getc(void); +void uart_putc(char c); +void uart_puts(char* str); + +#endif \ No newline at end of file diff --git a/lab8/bootloader/include/mm.h b/lab8/bootloader/include/mm.h new file mode 100644 index 000000000..119624a2b --- /dev/null +++ b/lab8/bootloader/include/mm.h @@ -0,0 +1,17 @@ +#ifndef _MM_H +#define _MM_H + +#define PAGE_SHIFT 12 +#define TABLE_SHIFT 9 +#define SECTION_SHIFT (PAGE_SHIFT + TABLE_SHIFT) + +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define SECTION_SIZE (1 << SECTION_SHIFT) + +#define LOW_MEMORY (2 * SECTION_SIZE) + +#ifndef __ASSEMBLER__ +void memzero(unsigned long src, unsigned long n); +#endif + +#endif \ No newline at end of file diff --git a/lab8/bootloader/include/peripherals/base.h b/lab8/bootloader/include/peripherals/base.h new file mode 100644 index 000000000..d7eb1f9b5 --- /dev/null +++ b/lab8/bootloader/include/peripherals/base.h @@ -0,0 +1,6 @@ +#ifndef _PER_BASE_H_ +#define _PER_BASE_H_ + +#define PHY_BASE_ADDR 0x3F000000 + +#endif \ No newline at end of file diff --git a/lab8/bootloader/include/peripherals/gpio.h b/lab8/bootloader/include/peripherals/gpio.h new file mode 100644 index 000000000..1132dae95 --- /dev/null +++ b/lab8/bootloader/include/peripherals/gpio.h @@ -0,0 +1,12 @@ +#ifndef _PER_GPIO_H +#define _PER_GPIO_H + +#include "peripherals/base.h" + +#define GPFSEL1 (PHY_BASE_ADDR + 0x00200004) +#define GPSET0 (PHY_BASE_ADDR + 0x0020001C) +#define GPCLR0 (PHY_BASE_ADDR + 0x00200028) +#define GPPUD (PHY_BASE_ADDR + 0x00200094) +#define GPPUDCLK0 (PHY_BASE_ADDR + 0x00200098) + +#endif \ No newline at end of file diff --git a/lab8/bootloader/include/peripherals/mini_uart.h b/lab8/bootloader/include/peripherals/mini_uart.h new file mode 100644 index 000000000..c08d34831 --- /dev/null +++ b/lab8/bootloader/include/peripherals/mini_uart.h @@ -0,0 +1,18 @@ +#ifndef _PER_MINI_UART_H_ +#define _PER_MINI_UART_H_ + +#include "peripherals/base.h" +#define AUX_ENABLES (PHY_BASE_ADDR + 0x00215004) +#define AUX_MU_IO_REG (PHY_BASE_ADDR + 0x00215040) +#define AUX_MU_IER_REG (PHY_BASE_ADDR + 0x00215044) +#define AUX_MU_IIR_REG (PHY_BASE_ADDR + 0x00215048) +#define AUX_MU_LCR_REG (PHY_BASE_ADDR + 0x0021504C) +#define AUX_MU_MCR_REG (PHY_BASE_ADDR + 0x00215050) +#define AUX_MU_LSR_REG (PHY_BASE_ADDR + 0x00215054) +#define AUX_MU_MSR_REG (PHY_BASE_ADDR + 0x00215058) +#define AUX_MU_SCRATCH (PHY_BASE_ADDR + 0x0021505C) +#define AUX_MU_CNTL_REG (PHY_BASE_ADDR + 0x00215060) +#define AUX_MU_STAT_REG (PHY_BASE_ADDR + 0x00215064) +#define AUX_MU_BAUD_REG (PHY_BASE_ADDR + 0x00215068) + +#endif \ No newline at end of file diff --git a/lab8/bootloader/include/shell.h b/lab8/bootloader/include/shell.h new file mode 100644 index 000000000..d588b1de9 --- /dev/null +++ b/lab8/bootloader/include/shell.h @@ -0,0 +1,26 @@ +#ifndef _SHELL_H +#define _SHELL_H + +void buffer_clear(); +void execute_command(char *); +void init_shell(); + +void print_input_prompt(); +void get_input(); + +void del_key(); +void left_key(); +void right_key(); +void up_key(); +void down_key(); + +void simple_shell(); + +void shell_hello(); +void shell_help(); +void shell_reboot(); +void shell_boot_uart(); + +void shell_ls(); + +#endif \ No newline at end of file diff --git a/lab8/bootloader/include/stdint.h b/lab8/bootloader/include/stdint.h new file mode 100644 index 000000000..ebc26e483 --- /dev/null +++ b/lab8/bootloader/include/stdint.h @@ -0,0 +1,18 @@ +#ifndef _STDINT_H +#define _STDINT_H + +typedef unsigned long long int uint64_t; +typedef signed long long int int64_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +typedef unsigned short int uint16_t; +typedef signed short int int16_t; + +typedef unsigned char uint8_t; +typedef signed char int8_t; + +uint8_t hex_to_int64(char*); +uint64_t hex_to_int8(char); +#endif \ No newline at end of file diff --git a/lab8/bootloader/include/str_tool.h b/lab8/bootloader/include/str_tool.h new file mode 100644 index 000000000..3d5018e36 --- /dev/null +++ b/lab8/bootloader/include/str_tool.h @@ -0,0 +1,24 @@ +#ifndef _STR_TOOL_H +#define _STR_TOOL_H +#include "stdint.h" + +typedef struct { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} cpio_newc_header; + +int strcmp(char*, char*); +char* itoa(int64_t, int); +#endif \ No newline at end of file diff --git a/lab8/bootloader/include/utils.h b/lab8/bootloader/include/utils.h new file mode 100644 index 000000000..99dfeecc6 --- /dev/null +++ b/lab8/bootloader/include/utils.h @@ -0,0 +1,8 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +void delay(unsigned long); +void put32(unsigned long, unsigned int); +unsigned int get32(unsigned long); + +#endif \ No newline at end of file diff --git a/lab8/bootloader/link.ld b/lab8/bootloader/link.ld new file mode 100644 index 000000000..dfbf24cf2 --- /dev/null +++ b/lab8/bootloader/link.ld @@ -0,0 +1,13 @@ +SECTIONS +{ + . = 0x50000; + .text : { KEEP(*(.text.boot)) *(.text) } + .rodata : { *(.rodata) } + .data : { *(.data) } + + . = ALIGN(0x8); + bss_begin = .; + .bss : { *(.bss*) } + bss_end = .; + _end = .; +} diff --git a/lab8/bootloader/main.c b/lab8/bootloader/main.c new file mode 100644 index 000000000..46afb4dfb --- /dev/null +++ b/lab8/bootloader/main.c @@ -0,0 +1,31 @@ +#include "mini_uart.h" +#include "utils.h" +#include "stdint.h" + +union large_int_by_byte{ + uint8_t int_by_byte[8]; + uint64_t larg_int; +}; + +void boot_main(){ + uart_init(); + + union large_int_by_byte program; + volatile uint8_t *program_addr = (volatile uint8_t *)0x80000; + + // read dirty message until end + while(1) { + uint8_t data; + data = uart_getc(); + if(data==4)break; + } + + // read kernel size + for(int i=0; i<8; i++) + program.int_by_byte[i] = uart_getc(); + + for(uint64_t offset=0; offset= '0' && hex <= '9') + return hex-'0'; + else if(hex >= 'A' && hex <= 'Z') + return hex-'A'+10; + else if(hex >= 'a' && hex <= 'z') + return hex-'a'+10; + else + return -1; +} + +uint64_t hex_to_int64(char* num){ + uint64_t res=0; + for(int i=0; i<8; i++){ + res = (res<<4) + hex_to_int8(num[i]); + } + return res; +} \ No newline at end of file diff --git a/lab8/bootloader/str_tool.c b/lab8/bootloader/str_tool.c new file mode 100644 index 000000000..cb955f297 --- /dev/null +++ b/lab8/bootloader/str_tool.c @@ -0,0 +1,23 @@ +#include "stdint.h" + +int strcmp(char *s1, char *s2){ + while(*s1!='\0' && *s2!='\0' && *s1==*s2){ + s1 += 1; + s2 += 1; + } + return *s1 - *s2; +} + +char* itoa(int64_t val, int base){ + static char buf[32] = {0}; + int i = 30; + if (val == 0) { + buf[i] = '0'; + return &buf[i]; + } + + for (; val && i; --i, val /= base) + buf[i] = "0123456789abcdef"[val % base]; + + return &buf[i + 1]; +} \ No newline at end of file diff --git a/lab8/bootloader/utils.S b/lab8/bootloader/utils.S new file mode 100644 index 000000000..e735f1dc7 --- /dev/null +++ b/lab8/bootloader/utils.S @@ -0,0 +1,15 @@ +.globl put32 +put32: + str w1, [x0] + ret + +.globl get32 +get32: + ldr w0, [x0] + ret + +.globl delay +delay: + subs x0, x0, #1 + bne delay + ret \ No newline at end of file diff --git a/lab8/bootloader/utils/mini_uart.c b/lab8/bootloader/utils/mini_uart.c new file mode 100644 index 000000000..46ca9cfe0 --- /dev/null +++ b/lab8/bootloader/utils/mini_uart.c @@ -0,0 +1,47 @@ +#include "utils.h" +#include "peripherals/gpio.h" +#include "peripherals/mini_uart.h" + +void uart_init(){ + unsigned int selector; + + selector = get32(GPFSEL1); + selector &= ~(7<<12); // clean gpio 14 + selector |= 2<<12; // set alt5 at gpio14 + selector &= ~(7<<15); // clean gpio 15 + selector |= 2<<15; // set alt5 at gpio 15 + put32(GPFSEL1, selector); + + put32(GPPUD, 0); // disable pull-up/down + delay(150); // wait 150 cycles + put32(GPPUDCLK0, (1<<14)|(1<<15)); // only modify GPIO 14 and 15 + delay(150); + put32(GPPUDCLK0, 0); // remove the clock + + put32(AUX_ENABLES, 1); // enable mini UART + put32(AUX_MU_CNTL_REG, 0); // Disable transmitter and receiver during configuration + put32(AUX_MU_IER_REG, 0); // Disable interrupt + put32(AUX_MU_LCR_REG, 3); // Set the data size to 8 bit + put32(AUX_MU_MCR_REG, 0); // Don’t need auto flow control + put32(AUX_MU_BAUD_REG, 270); // Set baud rate to 115200 + + put32(AUX_MU_IIR_REG, 6); // No FIFO + put32(AUX_MU_CNTL_REG, 3); // Enable the transmitter and receiver +} + +void uart_putc(char c){ + while(!(get32(AUX_MU_LSR_REG)&0x20)); + put32(AUX_MU_IO_REG, c); +} + +char uart_getc(void){ + while(!(get32(AUX_MU_LSR_REG)&0x01)); + return get32(AUX_MU_IO_REG); +} + +void uart_puts(char* str){ + while(*str){ + uart_putc(*str); + str += 1; + } +} \ No newline at end of file diff --git a/lab8/bootloader/utils/mm.S b/lab8/bootloader/utils/mm.S new file mode 100644 index 000000000..f9b279e14 --- /dev/null +++ b/lab8/bootloader/utils/mm.S @@ -0,0 +1,6 @@ +.globl memzero +memzero: + str xzr, [x0], #8 + subs x1, x1, #8 + b.gt memzero + ret \ No newline at end of file diff --git a/lab8/bootloader/utils/stdint.c b/lab8/bootloader/utils/stdint.c new file mode 100644 index 000000000..c41cc43ea --- /dev/null +++ b/lab8/bootloader/utils/stdint.c @@ -0,0 +1,21 @@ +typedef unsigned long long int uint64_t; +typedef unsigned char uint8_t; + +uint8_t hex_to_int8(char hex){ + if(hex >= '0' && hex <= '9') + return hex-'0'; + else if(hex >= 'A' && hex <= 'Z') + return hex-'A'+10; + else if(hex >= 'a' && hex <= 'z') + return hex-'a'+10; + else + return -1; +} + +uint64_t hex_to_int64(char* num){ + uint64_t res=0; + for(int i=0; i<8; i++){ + res = (res<<4) + hex_to_int8(num[i]); + } + return res; +} \ No newline at end of file diff --git a/lab8/bootloader/utils/str_tool.c b/lab8/bootloader/utils/str_tool.c new file mode 100644 index 000000000..cb955f297 --- /dev/null +++ b/lab8/bootloader/utils/str_tool.c @@ -0,0 +1,23 @@ +#include "stdint.h" + +int strcmp(char *s1, char *s2){ + while(*s1!='\0' && *s2!='\0' && *s1==*s2){ + s1 += 1; + s2 += 1; + } + return *s1 - *s2; +} + +char* itoa(int64_t val, int base){ + static char buf[32] = {0}; + int i = 30; + if (val == 0) { + buf[i] = '0'; + return &buf[i]; + } + + for (; val && i; --i, val /= base) + buf[i] = "0123456789abcdef"[val % base]; + + return &buf[i + 1]; +} \ No newline at end of file diff --git a/lab8/bootloader/utils/utils.S b/lab8/bootloader/utils/utils.S new file mode 100644 index 000000000..e735f1dc7 --- /dev/null +++ b/lab8/bootloader/utils/utils.S @@ -0,0 +1,15 @@ +.globl put32 +put32: + str w1, [x0] + ret + +.globl get32 +get32: + ldr w0, [x0] + ret + +.globl delay +delay: + subs x0, x0, #1 + bne delay + ret \ No newline at end of file diff --git a/lab8/config.txt b/lab8/config.txt new file mode 100644 index 000000000..261480683 --- /dev/null +++ b/lab8/config.txt @@ -0,0 +1,4 @@ +kernel_address=0x60000 +kernel=bootloader.img +arm_64bit=1 +initramfs initramfs.cpio 0x8000000 \ No newline at end of file diff --git a/lab8/kernel/FAT_R.txt b/lab8/kernel/FAT_R.txt new file mode 100644 index 000000000..5d2252cd1 --- /dev/null +++ b/lab8/kernel/FAT_R.txt @@ -0,0 +1 @@ +fat_r test \ No newline at end of file diff --git a/lab8/kernel/Makefile b/lab8/kernel/Makefile new file mode 100644 index 000000000..5da9abeca --- /dev/null +++ b/lab8/kernel/Makefile @@ -0,0 +1,66 @@ +CC = aarch64-linux-gnu-gcc +CFLAGS = -Iinclude -Wall -nostdlib -nostartfiles -ffreestanding +# ASMFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJCOPYFLAGS = -O binary + +QEMU = qemu-system-aarch64 + +BUILD_DIR = build +SRC_DIR = src + +all: initramfs.cpio kernel8.img + +initramfs.cpio: + cd rootfs; find . | cpio -o -H newc > ../initramfs.cpio; cd ..; + +clean: + rm $(BUILD_DIR)/* initramfs.cpio + +setup_loop_device: + sudo cp ../sfn_nctuos.img . + qemu-img resize sfn_nctuos.img 64M + sudo losetup -fP sfn_nctuos.img + sudo mount -t msdos /dev/loop23p1 image_mount + sudo cp FAT_R.txt image_mount + +remove_loop_device: + sudo umount image_mount + sudo losetup -d /dev/loop23 + +setup_sd: + sudo mount -t msdos /dev/ttyUSB0 sd_mount + +remove_sd: + sudo umount sd_mount + +$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c + mkdir -p $(@D) + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S + $(CC) $(ASMFLAGS) -c $< -o $@ + +C_FILES = $(wildcard $(SRC_DIR)/*.c) +ASM_FILES = $(wildcard $(SRC_DIR)/*.S) +OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o) +OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o) + +kernel8.elf: $(SRC_DIR)/linker.ld $(OBJ_FILES) + $(LD) -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf $(OBJ_FILES) + +kernel8.img: kernel8.elf + $(OBJCOPY) $(OBJCOPYFLAGS) $(BUILD_DIR)/kernel8.elf $(BUILD_DIR)/kernel8.img + +run: + $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -display none -serial null -serial stdio -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb -drive if=sd,file=sfn_nctuos.img,format=raw + +run1: + killall -9 qemu-system-aarch64 + $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -display vnc=127.0.0.4:0 -serial null -serial stdio -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + + +debug: + killall -9 qemu-system-aarch64 + $(QEMU) -M raspi3 -kernel $(BUILD_DIR)/kernel8.img -serial null -serial stdio -display none -S -s -initrd initramfs.cpio \ No newline at end of file diff --git a/lab8/kernel/gdb_file b/lab8/kernel/gdb_file new file mode 100644 index 000000000..8e9744669 --- /dev/null +++ b/lab8/kernel/gdb_file @@ -0,0 +1,2 @@ +file build/kernel8.elf +target remote :1234 \ No newline at end of file diff --git a/lab8/kernel/image_mount/bootcode.bin b/lab8/kernel/image_mount/bootcode.bin new file mode 100755 index 000000000..944263a65 Binary files /dev/null and b/lab8/kernel/image_mount/bootcode.bin differ diff --git a/lab8/kernel/image_mount/fat_r.txt b/lab8/kernel/image_mount/fat_r.txt new file mode 100755 index 000000000..5d2252cd1 --- /dev/null +++ b/lab8/kernel/image_mount/fat_r.txt @@ -0,0 +1 @@ +fat_r test \ No newline at end of file diff --git a/lab8/kernel/image_mount/fixup.dat b/lab8/kernel/image_mount/fixup.dat new file mode 100755 index 000000000..e928ee3fc Binary files /dev/null and b/lab8/kernel/image_mount/fixup.dat differ diff --git a/lab8/kernel/image_mount/kernel8.img b/lab8/kernel/image_mount/kernel8.img new file mode 100755 index 000000000..1b8fb854f Binary files /dev/null and b/lab8/kernel/image_mount/kernel8.img differ diff --git a/lab8/kernel/image_mount/start.elf b/lab8/kernel/image_mount/start.elf new file mode 100755 index 000000000..2f1fc7d33 Binary files /dev/null and b/lab8/kernel/image_mount/start.elf differ diff --git a/lab8/kernel/include/alloc.h b/lab8/kernel/include/alloc.h new file mode 100644 index 000000000..ff3819985 --- /dev/null +++ b/lab8/kernel/include/alloc.h @@ -0,0 +1,42 @@ +#pragma once +#include "utils.h" +#include +#define PAGE_BASE_ADDR ((uint64_t)0x10000000) +#define PAGE_END_ADDR ((uint64_t)0x20000000) +#define PAGE_SIZE ((uint64_t)(4 * kb)) +#define MAX_PAGE_NUM \ + ((uint64_t)((PAGE_END_ADDR - PAGE_BASE_ADDR) / PAGE_SIZE)) // 65536 +#define MAX_FRAME_ORDER 16 // 2^16 = 65536 +#define FRAME_LIST_NUM (MAX_FRAME_ORDER + 1) + +typedef struct PageFrame { + int id; + int order; + int is_allocated; + uint64_t addr; + struct PageFrame *next; +} page_frame; + +typedef struct DMAHeader { + uint64_t total_size; + uint64_t used_size; + int is_allocated; + page_frame *frame_ptr; + struct DMAHeader *prev, *next; +} dma_header; + +page_frame frames[MAX_PAGE_NUM]; +page_frame *free_frame_lists[FRAME_LIST_NUM], *used_frame_lists[FRAME_LIST_NUM]; + +dma_header *free_dma_list; + +void buddy_init(); +void buddy_test(); +page_frame *buddy_allocate(uint64_t size); +void buddy_free(page_frame *frame); +void buddy_unlink(int index, int type); +void print_frame_lists(); +void dma_test(); +void *malloc(uint64_t size); +void free(void *ptr); +void print_dma_list(); diff --git a/lab8/kernel/include/cpio.h b/lab8/kernel/include/cpio.h new file mode 100644 index 000000000..88808f90a --- /dev/null +++ b/lab8/kernel/include/cpio.h @@ -0,0 +1,66 @@ +#pragma once + +#include +#include +#include +#include "utils.h" + +#define RAMFS_ADDR 0x8000000 +#define CPIO_MAGIC "070701" +#define CPIO_END "TRAILER!!!" + +#define MAX_FILES_IN_DIR 20 +#define CPIOFS_BUF_SIZE (500 * kb) + +typedef struct { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} cpio_newc_header; + +void cpio_ls(); +void cpio_cat(char *filename); +uint32_t cpio_load_user_program(const char *target_program, + uint64_t target_addr); +void cpio_populate_rootfs(); + +struct cpiofs_file { + size_t size; + char *buffer; +}; + +struct cpiofs_fentry { + char name[20]; + FILE_TYPE type; + struct vnode* vnode; + struct vnode* parent_vnode; + struct cpiofs_fentry* child[MAX_FILES_IN_DIR]; + struct cpiofs_file* file; +}; + +struct vnode_operations* cpiofs_v_ops; +struct file_operations* cpiofs_f_ops; + +void cpiofs_init(); +void cpiofs_set_fentry(struct cpiofs_fentry* fentry, const char* component_name, + struct cpiofs_file* file, FILE_TYPE type, struct vnode* vnode); +int cpiofs_setup_mount(struct filesystem* fs, struct mount* mount); +int cpiofs_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name); +int cpiofs_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type); +int cpiofs_set_parent(struct vnode* child_node, struct vnode* parent_vnode); +int cpiofs_write(struct file* file, const void* buf, size_t len); +int cpiofs_read(struct file* file, void* buf, size_t len); +int cpiofs_list(struct file* file, void* buf, int index); diff --git a/lab8/kernel/include/delays.h b/lab8/kernel/include/delays.h new file mode 100644 index 000000000..ebbeb94ce --- /dev/null +++ b/lab8/kernel/include/delays.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +void wait_cycles(unsigned int n); +void wait_msec(unsigned int n); +unsigned long get_system_timer(); +void wait_msec_st(unsigned int n); diff --git a/lab8/kernel/include/device.h b/lab8/kernel/include/device.h new file mode 100644 index 000000000..9cfffa31b --- /dev/null +++ b/lab8/kernel/include/device.h @@ -0,0 +1,51 @@ +#pragma once +#include +#include "gpio.h" +#include "utils.h" +#include "vfs.h" +#include "uart.h" + +#define MAX_DEVICE_IN_DIR 16 + +typedef enum { DEV_ROOT, DEV_UART, DEV_NONE } DEV_TYPE; + +struct device_fentry { + char name[20]; + //FILE_TYPE type; // all FILE_REGULAR??? + DEV_TYPE type; + struct vnode* vnode; + struct vnode* parent_vnode; + struct device_fentry* child[MAX_DEVICE_IN_DIR]; +}; + +struct vnode_operations* device_v_ops; +struct file_operations* device_f_ops; + +void device_init(); +void device_set_fentry(struct device_fentry* fentry, const char* component_name, + struct vnode* vnode, DEV_TYPE type); +int device_setup_mount(struct filesystem* fs, struct mount* mount); +int device_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name); +int device_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type); +int _device_create(struct vnode* dir_node, + const char* component_name, DEV_TYPE type); +int device_set_parent(struct vnode* child_node, struct vnode* parent_vnode); +int device_write(struct file* file, const void* buf, size_t len); +int device_read(struct file* file, void* buf, size_t len); +void device_list(struct vnode* dir); + +void root_init(); + + + +/**********************************************/ +/* uart file system */ +/**********************************************/ + +struct vnode_operations* uartfs_v_ops; +struct file_operations* uartfs_f_ops; +void uartfs_init(); +int uartfs_read(struct file* file, void* buf, size_t len); +int uartfs_write(struct file* file, const void* buf, size_t len); diff --git a/lab8/kernel/include/dtb.h b/lab8/kernel/include/dtb.h new file mode 100644 index 000000000..f4dfc9163 --- /dev/null +++ b/lab8/kernel/include/dtb.h @@ -0,0 +1,38 @@ +#pragma once + +#include "utils.h" + +#define FDT_BEGIN_NODE (0x00000001) +#define FDT_END_NODE (0x00000002) +#define FDT_PROP (0x00000003) +#define FDT_NOP (0x00000004) +#define FDT_END (0x00000009) + +typedef struct { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +} fdt_header; + +void mailbox_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void gpio_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void rtx3080ti_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +void default_probe(uint64_t struct_addr, uint64_t strings_addr, int depth); +int check_compatibility(uint64_t struct_addr, uint64_t strings_addr, + char *compatible_name); + +void dtb_print(int all); +void dtb_parse(uint64_t struct_addr, uint64_t strings_addr, + void (*callback)(uint64_t, uint64_t, int)); +uint64_t ignore_current_node(uint64_t struct_addr, uint64_t strings_addr); +uint64_t print_node(uint64_t struct_addr, uint64_t strings_addr, int depth); +uint64_t print_property(uint64_t struct_addr, uint64_t strings_addr, int depth); +uint32_t dtb_read_int(uint64_t addr_ptr); +// char *dtb_read_string(uint64_t *addr_ptr); \ No newline at end of file diff --git a/lab8/kernel/include/exception.h b/lab8/kernel/include/exception.h new file mode 100644 index 000000000..b6e34b279 --- /dev/null +++ b/lab8/kernel/include/exception.h @@ -0,0 +1,12 @@ +#pragma once + +#include "gpio.h" +#include "utils.h" +#include +void sync_handler_currentEL_ELx(); +void sync_handler_lowerEL_64(uint64_t sp_addr); +void irq_handler_currentEL_ELx(); +void irq_handler_lowerEL_64(); +void default_handler(); +void enable_interrupt(); +void disable_interrupt(); \ No newline at end of file diff --git a/lab8/kernel/include/fatfs.h b/lab8/kernel/include/fatfs.h new file mode 100644 index 000000000..2ac49b46c --- /dev/null +++ b/lab8/kernel/include/fatfs.h @@ -0,0 +1,129 @@ +#pragma once + +#include +#include + +#include "utils.h" +#include "vfs.h" + +#define BLOCK_SIZE 512 +#define MBR_PARTITION_BASE 0x1BE +#define MAX_FILES_IN_DIR 20 +#define FATFS_BUF_SIZE (10 * kb) + +struct mbr_partition_entry { + unsigned char status_flag; // 0x0 + unsigned char partition_begin_head; // 0x1 + unsigned short partition_begin_sector; // 0x2 + unsigned char partition_type; // 0x4 + unsigned char partition_end_head; // 0x5 + unsigned short partition_end_sector; // 0x6 + unsigned int starting_sector; // 0x8 + unsigned int sector_count; // 0xC +} __attribute__((packed)); + +struct fatfs_boot_sector { + unsigned char bootjmp[3]; // 0x00 + unsigned char oem_name[8]; // 0x08 + unsigned short bytes_per_sector; // 0x0B + unsigned char sectors_per_cluster; // 0x0D + unsigned short reserved_sector_count; // 0x0E + unsigned char fat_count; // 0x10 + unsigned short root_entry_count; // 0x11 + unsigned short total_sectors; // 0x13 + unsigned char media_descriptor; // 0x15 + unsigned short sectors_per_fat; // 0x16 + unsigned short sectors_per_track; // 0x18 + unsigned short head_count; // 0x1A + unsigned int hidden_sector_count; // 0x1C + unsigned int total_sectors_32; // 0x20 + unsigned int sectors_per_fat_32; // 0x24 + unsigned short mirror_flags; // 0x28 + unsigned short fat_version; // 0x2A + unsigned int root_cluster; // 0x2C + unsigned short info_sector_number; // 0x30 + unsigned short backup_boot_sector_count; // 0x32 + unsigned char reserved_0[12]; // 0x34 + unsigned char drive_number; // 0x40 + unsigned char reserved_1; // 0x41 + unsigned char boot_signature; // 0x42 + unsigned int volume_id; // 0x43 + unsigned char volume_label[11]; // 0x47 + unsigned char fat_type_label[8]; // 0x52 +} __attribute__((packed)); + +struct fatfs_dentry { + unsigned char filename[8]; // 0x00 + unsigned char extension[3]; // 0x08 + uint8_t file_attr; // 0x0B + unsigned char reserved; // 0x0C + uint8_t created_time_ms; // 0x0D + unsigned short created_time; // 0x0E + unsigned short created_date; // 0x10 + unsigned short last_modified_date_stamp; // 0x12 + unsigned short cluster_high; // 0x14 + unsigned short last_modified_time; // 0x16 + unsigned short last_modified_date; // 0x18 + unsigned short cluster_low; // 0x1A + unsigned int file_size; // 0x1C +} __attribute__((packed)); + + +// struct mbr_partition_entry { +// char b[8]; +// unsigned short addr; +// char c[6]; +// }; + +// struct mbr { +// unsigned char bootstrap_code[0x1BE]; +// struct mbr_partition_entry entries[4]; +// // unsigned char b[64]; +// unsigned char boot_signature[2]; +// } __attribute__((packed)); + + +struct fatfs_buf { + int flag; + size_t size; + char buffer[FATFS_BUF_SIZE]; +}; + +struct fatfs_fentry { + char name[20]; + int name_len; // test1.txt -> 5 (before .) + int starting_cluster; + FILE_TYPE type; + struct vnode* vnode; + struct vnode* parent_vnode; + struct fatfs_fentry* child[MAX_FILES_IN_DIR]; + struct fatfs_buf* buf; +}; + +struct fatfs_boot_sector* fat_boot_sector; +struct fatfs_dentry* fat_root_dentry; +int fat_starting_sector; +int data_starting_sector; +int root_starting_sector; +int current_starting_sector; + +struct vnode_operations* fatfs_v_ops; +struct file_operations* fatfs_f_ops; + +void fatfs_init(); +void fatfs_set_directory(struct fatfs_fentry* fentry, + struct fatfs_dentry* dentry); +void list_sd(); +void fatfs_set_fentry(struct fatfs_fentry* fentry, FILE_TYPE type, + struct vnode* vnode, int starting_cluster, int buf_size); +int fatfs_setup_mount(struct filesystem* fs, struct mount* mount); +int fatfs_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name); +int fatfs_set_parent(struct vnode* child_node, struct vnode* parent_vnode); +int fatfs_write(struct file* file, const void* buf, size_t len); +int fatfs_read(struct file* file, void* buf, size_t len); +int fatfs_list(struct file* file, void* buf, int index); + +int fatfs_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type); + diff --git a/lab8/kernel/include/gpio.h b/lab8/kernel/include/gpio.h new file mode 100644 index 000000000..52fa671d0 --- /dev/null +++ b/lab8/kernel/include/gpio.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#define MMIO_BASE 0x3F000000 + +#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000)) +#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004)) +#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008)) +#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C)) +#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010)) +#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014)) +#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C)) +#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020)) +#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028)) +#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034)) +#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038)) +#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040)) +#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044)) +#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064)) +#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068)) +#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094)) +#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098)) +#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C)) diff --git a/lab8/kernel/include/math.h b/lab8/kernel/include/math.h new file mode 100644 index 000000000..b3c6a317f --- /dev/null +++ b/lab8/kernel/include/math.h @@ -0,0 +1,6 @@ +#ifndef MATH_H +#define MATH_H + +int pow(int base, int exponent); + +#endif \ No newline at end of file diff --git a/lab8/kernel/include/mbox.h b/lab8/kernel/include/mbox.h new file mode 100644 index 000000000..b08665886 --- /dev/null +++ b/lab8/kernel/include/mbox.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/* a properly aligned buffer */ +extern unsigned int mbox[36]; + +#define MBOX_REQUEST 0 + +/* channels */ +#define MBOX_CH_POWER 0 +#define MBOX_CH_FB 1 +#define MBOX_CH_VUART 2 +#define MBOX_CH_VCHIQ 3 +#define MBOX_CH_LEDS 4 +#define MBOX_CH_BTNS 5 +#define MBOX_CH_TOUCH 6 +#define MBOX_CH_COUNT 7 +#define MBOX_CH_PROP 8 + +/* tags */ +#define MBOX_TAG_SETPOWER 0x28001 +#define MBOX_TAG_SETCLKRATE 0x38002 +#define MBOX_TAG_GETSERIAL 0x10004 +#define MBOX_TAG_GETBDVS 0x00010002 +#define MBOX_TAG_GETARMMEM 0x00010005 + +#define MBOX_TAG_LAST 0 + +int mbox_call(unsigned char ch, unsigned int* mbox); diff --git a/lab8/kernel/include/power.h b/lab8/kernel/include/power.h new file mode 100644 index 000000000..4216fa556 --- /dev/null +++ b/lab8/kernel/include/power.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +void power_off(); +void reset(); diff --git a/lab8/kernel/include/printf.h b/lab8/kernel/include/printf.h new file mode 100644 index 000000000..e58f666dc --- /dev/null +++ b/lab8/kernel/include/printf.h @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. +// Use this instead of bloated standard/newlib printf. +// These routines are thread safe and reentrant. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _PRINTF_H_ +#define _PRINTF_H_ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Output a character to a custom device like UART, used by the printf() function + * This function is declared here only. You have to write your custom implementation somewhere + * \param character Character to output + */ +void _putchar(char character); + + +/** + * Tiny printf implementation + * You have to implement _putchar if you use printf() + * To avoid conflicts with the regular printf() API it is overridden by macro defines + * and internal underscore-appended functions like printf_() are used + * \param format A string that specifies the format of the output + * \return The number of characters that are written into the array, not counting the terminating null character + */ +#define printf printf_ +int printf_(const char* format, ...); + + +/** + * Tiny sprintf implementation + * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD! + * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output! + * \param format A string that specifies the format of the output + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define sprintf sprintf_ +int sprintf_(char* buffer, const char* format, ...); + + +/** + * Tiny snprintf/vsnprintf implementation + * \param buffer A pointer to the buffer where to store the formatted string + * \param count The maximum number of characters to store in the buffer, including a terminating null character + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that COULD have been written into the buffer, not counting the terminating + * null character. A value equal or larger than count indicates truncation. Only when the returned value + * is non-negative and less than count, the string has been completely written. + */ +#define snprintf snprintf_ +#define vsnprintf vsnprintf_ +int snprintf_(char* buffer, size_t count, const char* format, ...); +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); + + +/** + * Tiny vprintf implementation + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define vprintf vprintf_ +int vprintf_(const char* format, va_list va); + + +/** + * printf with output function + * You may use this as dynamic alternative to printf() with its fixed _putchar() output + * \param out An output function which takes one character and an argument pointer + * \param arg An argument pointer for user data passed to output function + * \param format A string that specifies the format of the output + * \return The number of characters that are sent to the output function, not counting the terminating null character + */ +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); + + +#ifdef __cplusplus +} +#endif + + +#endif // _PRINTF_H_ \ No newline at end of file diff --git a/lab8/kernel/include/sdhost.h b/lab8/kernel/include/sdhost.h new file mode 100644 index 000000000..7c780545e --- /dev/null +++ b/lab8/kernel/include/sdhost.h @@ -0,0 +1,14 @@ +#pragma once + +// static inline void delay(unsigned long tick); +// static void pin_setup(); +// static void sdhost_setup(); +// static int wait_sd(); +// static int sd_cmd(unsigned cmd, unsigned int arg); +// static int sdcard_setup(); +// static int wait_fifo(); +// static void set_block(int size, int cnt); +// static void wait_finish(); +void readblock(int block_idx, void* buf); +void writeblock(int block_idx, void* buf); +void sd_init(); \ No newline at end of file diff --git a/lab8/kernel/include/shell.h b/lab8/kernel/include/shell.h new file mode 100644 index 000000000..1f7075b10 --- /dev/null +++ b/lab8/kernel/include/shell.h @@ -0,0 +1,32 @@ +#include "uart.h" +#include "string.h" +#include "power.h" +#include "mbox.h" +#include "cpio.h" +#include "timer.h" +#include "exception.h" +#include "alloc.h" +#include "utils.h" +#include "thread.h" +#include "printf.h" +// #include "device_tree.h" +#define RAMFS_ADDR 0x8000000 + +void clean_buffer(char * buffer, int buffer_len); +void command_help(); +void command_hello(); +void command_not_found(char * buffer); +void command_ls(); +void command_cat(char* pathname); +void command_mailbox(); +void command_test(); +void command_load_user_program(const char *program_name); +void command_set_timeout(char *args); +void command_buddy_test(); +void command_dma_test(); +void command_thread_test1() ; +void command_thread_test2() ; +void command_thread_test3() ; +void command_thread_test4() ; +void parse_command(char * buffer); +void run_shell(); diff --git a/lab8/kernel/include/string.h b/lab8/kernel/include/string.h new file mode 100644 index 000000000..44b3b5416 --- /dev/null +++ b/lab8/kernel/include/string.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +int strcmp(const char *p1, const char *p2); +int strncmp(const char *s1, const char *s2, unsigned n); +int strlen(const char *s); +char *strstr(const char *s, const char *find); +char *strcpy(char *dst, const char *src); +char *strncpy(char *destination, const char *source, size_t len); +void strcat(char *to, const char *from); +char *strtok(char *s, const char delim); +char *split_last(char *str, char delim); \ No newline at end of file diff --git a/lab8/kernel/include/thread.h b/lab8/kernel/include/thread.h new file mode 100644 index 000000000..222838650 --- /dev/null +++ b/lab8/kernel/include/thread.h @@ -0,0 +1,88 @@ +#pragma once + +#include "utils.h" +#include "vfs.h" + +#define STACK_SIZE 4096 +#define USER_PROGRAM_BASE 0x30000000 +#define USER_PROGRAM_SIZE (1 * mb) + +#define THREAD_DEAD 1 +#define THREAD_FORK 2 +#define THREAD_READY 4 + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +#define FD_MAX 256 + +typedef struct { + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t fp; + uint64_t lr; + uint64_t sp; +} cpu_context; + +typedef struct { + struct file *files[FD_MAX]; +} fd_table_t; + +typedef struct thread_info { + cpu_context context; + uint32_t pid; + uint32_t child_pid; + int status; + uint64_t trap_frame_addr; + uint64_t kernel_stack_base; + uint64_t user_stack_base; + uint64_t user_program_base; + uint32_t user_program_size; + fd_table_t fd_table; + struct thread_info *next; +} thread_info; + +typedef struct { + thread_info *head, *tail; +} thread_queue; + +typedef struct { + uint64_t x[31]; +} trap_frame_t; + +thread_queue run_queue; +uint32_t thread_cnt; + +extern thread_info *get_current(); +extern void switch_to(thread_info *, thread_info *); + +void foo(); +void thread_test1(); +void thread_test2(); +void thread_test3(); +void thread_test4(); + +void thread_init(); +thread_info *thread_create(void (*func)()); +void schedule(); +void idle(); +void exit(); +void run_queue_push(thread_info *thread); +void kill_zombies(); +void exec(const char *program_name, const char **argv); +void fork(uint64_t sp); +void handle_fork(); +void create_child(thread_info *parent, thread_info *child); +void kill (int kill_pid); + +struct file *thread_get_file(int fd); +int thread_register_fd(struct file *file); +int thread_clear_fd(int fd); \ No newline at end of file diff --git a/lab8/kernel/include/timer.h b/lab8/kernel/include/timer.h new file mode 100644 index 000000000..e42bee18d --- /dev/null +++ b/lab8/kernel/include/timer.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#define CORE0_TIMER_IRQ_CTRL ((volatile unsigned int *)(0x40000040)) +#define CORE0_INTERRUPT_SOURCE ((volatile unsigned int *)(0x40000060)) + +typedef struct timeout_event { + uint32_t register_time; + uint32_t duration; + void (*callback)(char *); + char args[20]; + struct timeout_event *prev, *next; +} timeout_event; + +timeout_event *timeout_queue_head, *timeout_queue_tail; + +void timeout_event_init(); +void core_timer_enable(); +void core_timer_disable(); +void core_timer_handler_lowerEL_64(); +void core_timer_handler_currentEL_ELx(); +void add_timer(void (*callback)(char *), char *args, uint32_t duration); +uint64_t get_current_time(); +void set_expired_time(uint32_t duration); +void timer_callback(char *msg); \ No newline at end of file diff --git a/lab8/kernel/include/tmpfs.h b/lab8/kernel/include/tmpfs.h new file mode 100644 index 000000000..1040885fd --- /dev/null +++ b/lab8/kernel/include/tmpfs.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include "utils.h" +#include "vfs.h" + +#define MAX_FILES_IN_DIR 20 +#define TMPFS_BUF_SIZE (500 * kb) + +struct tmpfs_buf { + int flag; + size_t size; + char buffer[TMPFS_BUF_SIZE]; +}; + +struct tmpfs_fentry { + char name[20]; + FILE_TYPE type; + struct vnode* vnode; + struct vnode* parent_vnode; + struct tmpfs_fentry* child[MAX_FILES_IN_DIR]; + struct tmpfs_buf* buf; +}; + +struct vnode_operations* tmpfs_v_ops; +struct file_operations* tmpfs_f_ops; + +void tmpfs_init(); +void tmpfs_set_fentry(struct tmpfs_fentry* fentry, const char* component_name, + FILE_TYPE type, struct vnode* vnode); +int tmpfs_setup_mount(struct filesystem* fs, struct mount* mount); +int tmpfs_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name); +int tmpfs_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type); +int tmpfs_set_parent(struct vnode* child_node, struct vnode* parent_vnode); +int tmpfs_write(struct file* file, const void* buf, size_t len); +int tmpfs_read(struct file* file, void* buf, size_t len); +int tmpfs_list(struct file* file, void* buf, int index); \ No newline at end of file diff --git a/lab8/kernel/include/uart.h b/lab8/kernel/include/uart.h new file mode 100644 index 000000000..e81ea48cf --- /dev/null +++ b/lab8/kernel/include/uart.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#pragma once +#include "gpio.h" +#include "vfs.h" +#include + +#define ARM_IRQ_REG_BASE (MMIO_BASE + 0x0000b000) + +#define IRQ_PENDING_1 ((volatile unsigned int *)(ARM_IRQ_REG_BASE + 0x00000204)) +#define ENABLE_IRQS_1 ((volatile unsigned int *)(ARM_IRQ_REG_BASE + 0x00000210)) +#define DISABLE_IRQS_1 \ + ((volatile unsigned int *)(ARM_IRQ_REG_BASE + 0x0000021c)) + +#define AUX_IRQ (1 << 29) + +#define UART_BUFFER_SIZE 20 +char read_buf[UART_BUFFER_SIZE]; +char write_buf[UART_BUFFER_SIZE]; +int read_buf_start, read_buf_end; +int write_buf_start, write_buf_end; + +void uart_init(); +void uart_send(unsigned int c); +char uart_getc(); +uint32_t uart_gets(char *buf, uint32_t size); +void uart_puts(char *s); +void uart_hex(unsigned int d); +void uart_putc(char c); +void uart_int(int x); +uint32_t uart_write(char *s, uint32_t size); + +void enable_uart_interrupt(); +void disable_uart_interrupt(); +void assert_transmit_interrupt(); +void clear_transmit_interrupt(); +void uart_handler(); +char uart_async_getc(); +void uart_async_puts(char *str); \ No newline at end of file diff --git a/lab8/kernel/include/utils.h b/lab8/kernel/include/utils.h new file mode 100644 index 000000000..085a90b13 --- /dev/null +++ b/lab8/kernel/include/utils.h @@ -0,0 +1,15 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ +#include +uint64_t hex_to_int64(char* num); +uint8_t hex_to_int8(char hex); +uint64_t hex2int(char *hex, int len); +uint64_t align_up(uint64_t addr, uint64_t alignment); +uint64_t align_up_exp(uint64_t n); +#define kb ((uint64_t)0x400) +#define mb ((uint64_t)0x100000) +#define gb ((uint64_t)0x40000000) +uint64_t log2(uint64_t num); +void delay(int num); +uint32_t be2le(uint32_t x); +#endif diff --git a/lab8/kernel/include/vfs.h b/lab8/kernel/include/vfs.h new file mode 100644 index 000000000..08c3321a1 --- /dev/null +++ b/lab8/kernel/include/vfs.h @@ -0,0 +1,81 @@ +#pragma once + +#include + +#define O_CREAT 00000100 + +typedef enum { FILE_DIRECTORY, FILE_REGULAR, FILE_DEVICE, FILE_NONE } FILE_TYPE; +typedef enum { STDIN, STDOUT, STDERR } FILENO; + +struct vnode { + struct mount* mount; + struct vnode_operations* v_ops; + struct file_operations* f_ops; + void* internal; +}; + +struct file { + struct vnode* vnode; + size_t f_pos; // The next read/write position of this opened file + struct file_operations* f_ops; + int flags; +}; + +struct mount { + struct vnode* root; + struct filesystem* fs; + char mount_entry[20]; +}; + +struct filesystem { + const char* name; + int (*setup_mount)(struct filesystem* fs, struct mount* mount); + struct filesystem* next; +}; + +struct filesystem_list { + struct filesystem *head, *tail; +}; + +struct file_operations { + int (*write)(struct file* file, const void* buf, size_t len); + int (*read)(struct file* file, void* buf, size_t len); + int (*list)(struct file* file, void* buf, int index); +}; + +struct vnode_operations { + int (*lookup)(struct vnode* dir_node, struct vnode** target, + const char* component_name); + int (*create)(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type); + int (*set_parent)(struct vnode* child_node, struct vnode* parent_node); +}; + +// file system +struct file * stdin; +struct file * stdout; +struct file * stderr; + +struct filesystem_list fs_list; +struct mount* rootfs; +struct vnode* current_dir; + +void vfs_test(); +void vfs_ls_test(); +void vfs_hard_test(); +void vfs_fat_test(); + +void vfs_init(); +int register_filesystem(struct filesystem* fs); +struct filesystem* get_fs_by_name(const char* name); +int vfs_find_vnode(struct vnode** target, const char* pathname); +struct file* vfs_open(const char* pathname, int flags); +int vfs_close(struct file* file); +int vfs_write(struct file* file, const void* buf, size_t len); +int vfs_read(struct file* file, void* buf, size_t len); +int vfs_list(struct file* file, void* buf, int index); +int vfs_mkdir(const char* pathname); +int vfs_chdir(const char* pathname); +int vfs_mount(const char* device, const char* mountpoint, + const char* filesystem); +int vfs_umount(const char* mountpoint); \ No newline at end of file diff --git a/lab8/kernel/initramfs/argv_test b/lab8/kernel/initramfs/argv_test new file mode 100755 index 000000000..bab6dec40 Binary files /dev/null and b/lab8/kernel/initramfs/argv_test differ diff --git a/lab8/kernel/initramfs/fork_test b/lab8/kernel/initramfs/fork_test new file mode 100755 index 000000000..77f02bab8 Binary files /dev/null and b/lab8/kernel/initramfs/fork_test differ diff --git a/lab8/kernel/initramfs/my_test b/lab8/kernel/initramfs/my_test new file mode 100755 index 000000000..347d3283c Binary files /dev/null and b/lab8/kernel/initramfs/my_test differ diff --git a/lab8/kernel/initramfs/my_test2 b/lab8/kernel/initramfs/my_test2 new file mode 100755 index 000000000..18d7dbebb Binary files /dev/null and b/lab8/kernel/initramfs/my_test2 differ diff --git a/lab8/kernel/initramfs/svc_test b/lab8/kernel/initramfs/svc_test new file mode 100755 index 000000000..1b407b1fa Binary files /dev/null and b/lab8/kernel/initramfs/svc_test differ diff --git a/lab8/kernel/initramfs/vfs1.img b/lab8/kernel/initramfs/vfs1.img new file mode 100644 index 000000000..2c41bd71a Binary files /dev/null and b/lab8/kernel/initramfs/vfs1.img differ diff --git a/lab8/kernel/sd_backup/FAT_R.txt b/lab8/kernel/sd_backup/FAT_R.txt new file mode 100644 index 000000000..5d2252cd1 --- /dev/null +++ b/lab8/kernel/sd_backup/FAT_R.txt @@ -0,0 +1 @@ +fat_r test \ No newline at end of file diff --git a/lab8/kernel/sd_backup/bootcode.bin b/lab8/kernel/sd_backup/bootcode.bin new file mode 100644 index 000000000..944263a65 Binary files /dev/null and b/lab8/kernel/sd_backup/bootcode.bin differ diff --git a/lab8/kernel/sd_backup/config.txt b/lab8/kernel/sd_backup/config.txt new file mode 100644 index 000000000..6b881d6c8 --- /dev/null +++ b/lab8/kernel/sd_backup/config.txt @@ -0,0 +1,3 @@ +kernel=kernel8.img +arm_64bit=1 +initramfs user.abc 0x8000000 \ No newline at end of file diff --git a/lab8/kernel/sd_backup/fixup.dat b/lab8/kernel/sd_backup/fixup.dat new file mode 100644 index 000000000..e928ee3fc Binary files /dev/null and b/lab8/kernel/sd_backup/fixup.dat differ diff --git a/lab8/kernel/sd_backup/kernel8.img b/lab8/kernel/sd_backup/kernel8.img new file mode 100755 index 000000000..3708476e5 Binary files /dev/null and b/lab8/kernel/sd_backup/kernel8.img differ diff --git a/lab8/kernel/sd_backup/start.elf b/lab8/kernel/sd_backup/start.elf new file mode 100644 index 000000000..2f1fc7d33 Binary files /dev/null and b/lab8/kernel/sd_backup/start.elf differ diff --git a/lab8/kernel/sd_backup/user.abc b/lab8/kernel/sd_backup/user.abc new file mode 100644 index 000000000..e7d8de591 Binary files /dev/null and b/lab8/kernel/sd_backup/user.abc differ diff --git a/lab8/kernel/sfn_nctuos.img b/lab8/kernel/sfn_nctuos.img new file mode 100644 index 000000000..0c12e7e3d Binary files /dev/null and b/lab8/kernel/sfn_nctuos.img differ diff --git a/lab8/kernel/src/alloc.c b/lab8/kernel/src/alloc.c new file mode 100644 index 000000000..a4d026a16 --- /dev/null +++ b/lab8/kernel/src/alloc.c @@ -0,0 +1,446 @@ +#include "alloc.h" +#include "uart.h" +#include "utils.h" +#include "printf.h" + +void buddy_test() { + print_frame_lists(); + uint64_t size[6] = { + PAGE_SIZE * 1, PAGE_SIZE * 13, PAGE_SIZE * 16, + PAGE_SIZE * 2, PAGE_SIZE * 4, PAGE_SIZE * 8, + }; + page_frame *frame_ptr[6]; + printf("********** buddy allocation test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + frame_ptr[i] = buddy_allocate(size[i]); + printf("Successfully allocate %lld pages\n", size[i] / PAGE_SIZE); + // if (c == 'p') + print_frame_lists(); + } + print_frame_lists(); + printf("********** buddy free test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + buddy_free(frame_ptr[i]); + printf("Successfully free %lld pages\n", size[i] / PAGE_SIZE); + // if (c == 'p') + print_frame_lists(); + } +} + +void dma_test() { + print_frame_lists(); + print_dma_list(); + // int *ptr1 = malloc(sizeof(int)); + // int *ptr2 = malloc(sizeof(int) * 1024); + // int *ptr3 = malloc(sizeof(int)); + // print_dma_list(); + // free(ptr1); + // print_dma_list(); + // free(ptr2); + // print_dma_list(); + // free(ptr3); + + uint64_t size[6] = { + sizeof(int) * 1, sizeof(int) * 8, sizeof(int) * 2201, + sizeof(int) * 9, sizeof(int) * 3068, sizeof(int) * 100, + }; + void *ptr[6]; + + printf("********** malloc test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + ptr[i] = malloc(size[i]); + printf("Successfully allocate %lld bytes in address %p\n", size[i], ptr[i]); + // if (c == 'p') { + print_frame_lists(); + print_dma_list(); // printf( + // "put frame index %d back to free lists (4K x 2^%lld = %lld KB)\n", + // id, frames[id].order, 1 << (frames[id].order + 2)); + // } + } + // print_frame_lists(); + // print_dma_list(); + printf("********** free test **********\n"); + for (int i = 0; i < 6; i++) { + printf("Press any key to continue..."); + char c = uart_getc(); + if (c != '\n') printf("\n"); + free(ptr[i]); + printf("Successfully free %lld bytes in address %p\n", size[i], ptr[i]); + // if (c == 'p') { + print_frame_lists(); + print_dma_list(); + // } + } +} + +void buddy_init() { + for (int i = 0; i < MAX_PAGE_NUM; i++) { + frames[i].id = i; + frames[i].order = -1; + frames[i].is_allocated = 0; + frames[i].addr = PAGE_BASE_ADDR + i * PAGE_SIZE; + frames[i].next = 0; + } + for (int i = 0; i < FRAME_LIST_NUM; i++) { + free_frame_lists[i] = 0; + used_frame_lists[i] = 0; + } + frames[0].order = MAX_FRAME_ORDER; + free_frame_lists[MAX_FRAME_ORDER] = &frames[0]; + free_dma_list = 0; +} + +page_frame * buddy_allocate(uint64_t size) { + // printf("Enter size (kb): "); + // int kb_size = read_i(); + uint64_t page_num = size / PAGE_SIZE; + if (size % PAGE_SIZE != 0) page_num++; + page_num = align_up_exp(page_num); + uint64_t order = log2(page_num); + + for (uint64_t i = order; i <= MAX_FRAME_ORDER; i++) { + // printf("i = "); + // uart_int(i); + // printf("\n"); + + if (free_frame_lists[i]) { + int cur_id = free_frame_lists[i]->id; + free_frame_lists[i] = free_frame_lists[i]->next; + frames[cur_id].order = order; + frames[cur_id].is_allocated = 1; + frames[cur_id].next = used_frame_lists[order]; + used_frame_lists[order] = &frames[cur_id]; + // printf("allocate frame index %d (4K x 2^%lld = %lld KB)\n", cur_id, order, + // 1 << (order + 2)); + + // release redundant memory block + for (; i > order; i--) { + int id = cur_id + (1 << (i - 1)); + frames[id].order = i - 1; + frames[id].is_allocated = 0; + frames[id].next = free_frame_lists[i - 1]; + free_frame_lists[i - 1] = &frames[id]; + // printf( + // "put frame index %d back to free lists (4K x 2^%lld = %lld KB)\n", + // id, frames[id].order, 1 << (frames[id].order + 2)); + } + // printf("\n"); + // print_frame_lists(); + return &frames[cur_id]; + } + } + return 0; +} + +void buddy_free(page_frame *frame) { + // printf("Enter address (hex): "); + // uint64_t addr = read_h(); + uint64_t index = frame->id; + if (!frames[index].is_allocated) { + printf("Error: it is already free\n"); + return; + } + uint64_t order = frames[index].order; + // printf("index :"); + // uart_int(index); + // printf("order :"); + // uart_int(order); + // printf("\n"); + buddy_unlink(index, 1); + // iterative merge + while (order <= MAX_FRAME_ORDER) { + uint64_t target_index = index ^ (1 << order); // XOR to find same size page + // printf("target_index :"); + // uart_int(target_index); + // printf("\n"); + if ((target_index >= MAX_PAGE_NUM) || frames[target_index].is_allocated || + (frames[target_index].order != order)) + break; + + // printf("merge with frame index %d (4K x 2^%lld = %lld KB)\n", target_index, + // frames[target_index].order, 1 << (frames[target_index].order + 2)); + order += 1; + // iterative part + if (index > target_index) index = target_index; + } + frames[index].order = order; + frames[index].next = free_frame_lists[order]; + free_frame_lists[order] = &frames[index]; + // printf("put frame index %d back (4K x 2^%lld = %lld KB)\n", index, + // frames[index].order, 1 << (frames[index].order + 2)); + // print_frame_lists(); +} + +void buddy_unlink(int index, int type) { + uint64_t order = frames[index].order; + frames[index].order = -1; + frames[index].is_allocated = 0; + + if (type == 0) { + if (free_frame_lists[order] == &frames[index]) { + free_frame_lists[order] = frames[index].next; + frames[index].next = 0; + } else { + // printf("=========linked list search free=======\n"); + for (page_frame *cur = free_frame_lists[order]; cur; cur = cur->next) { + if (cur->next == &frames[index]) { + cur->next = frames[index].next; + frames[index].next = 0; + break; + } + } + } + } + if (type == 1) { + if (used_frame_lists[order] == &frames[index]) { + used_frame_lists[order] = frames[index].next; + frames[index].next = 0; + } else { + // printf("=========linked list search used=======\n"); + for (page_frame *cur = used_frame_lists[order]; cur; cur = cur->next) { + if (cur->next == &frames[index]) { + cur->next = frames[index].next; + frames[index].next = 0; + break; + } + } + } + } +} + +void print_frame_lists() { + printf("========================\n"); + printf("Free frame lists: \n"); + for (int i = MAX_FRAME_ORDER; i >= 0; i--) { + printf("4K x 2^%d (%d KB):", i, 1 << (i + 2)); + for (page_frame *cur = free_frame_lists[i]; cur; cur = cur->next) { + printf(" index %d(0x%x)", cur->id, cur->addr); + } + printf("\n"); + } + printf("\n"); + printf("Used frame lists: \n"); + for (int i = MAX_FRAME_ORDER; i >= 0; i--) { + printf("4K x 2^%d (%d KB):", i, 1 << (i + 2)); + for (page_frame *cur = used_frame_lists[i]; cur; cur = cur->next) { + printf(" index %d(0x%x)", cur->id, cur->addr); + } + printf("\n"); + } + printf("========================\n"); +} + +void *malloc(uint64_t size) { + dma_header *free_slot = 0; + uint64_t min_size = ((uint64_t)1) << 63; + // printf("min_size :"); + // uart_int(min_size); + // printf("\n"); + // printf("size :"); + // uart_int(size); + // printf("\n"); + // find the smallest free slot which is bigger than the required size + for (dma_header *cur = free_dma_list; cur; cur = cur->next) { + // printf("find the smallest free slot which is bigger than the required size\n"); + + uint64_t data_size = cur->total_size - align_up(sizeof(dma_header), 8); + if (data_size >= align_up(size, 8) && data_size < min_size) { + free_slot = cur; + min_size = data_size; + } + } + + uint64_t allocated_size = align_up(sizeof(dma_header), 8) + align_up(size, 8); + // printf("allocated_size :"); + // uart_int(allocated_size); + // printf("\n"); + if (free_slot) { + // printf("have free_slot\n"); + + uint64_t addr = (uint64_t)free_slot; + uint64_t total_size = free_slot->total_size; + // rewrite the found free slot + free_slot->total_size = allocated_size; + free_slot->used_size = size; + free_slot->is_allocated = 1; + if (free_slot->prev) { + // printf("if (free_slot->prev)\n"); + free_slot->prev->next = free_slot->next; + } + if (free_slot->next) { + // printf("if (free_slot->next)\n"); + free_slot->next->prev = free_slot->prev; + } + if (free_dma_list == free_slot){ + // printf("if (free_slot->prev)\n"); + free_dma_list = free_slot->next; + } + free_slot->prev = 0; + free_slot->next = 0; + + // create another free slot if remaining size is big enough + int64_t free_size = + total_size - allocated_size - align_up(sizeof(dma_header), 8); + if (free_size > 0) { + dma_header *new_header = (dma_header *)(addr + allocated_size); + new_header->total_size = total_size - allocated_size; + new_header->used_size = 0; + new_header->is_allocated = 0; + new_header->frame_ptr = free_slot->frame_ptr; + new_header->prev = 0; + new_header->next = free_dma_list; + if (free_dma_list) free_dma_list->prev = new_header; + free_dma_list = new_header; + } else { + free_slot->total_size = total_size; + } + return (void *)(addr + align_up(sizeof(dma_header), 8)); + } else { + // printf("no free_slot\n"); + + // allocate a page + page_frame *frame_ptr = buddy_allocate(allocated_size); + uint64_t addr = frame_ptr->addr; + // printf("addr :"); + // uart_hex(addr); + // printf("\n"); + // create a free slot + dma_header *allocated_header = (dma_header *)addr; + allocated_header->total_size = allocated_size; + allocated_header->used_size = size; + allocated_header->is_allocated = 1; + allocated_header->frame_ptr = frame_ptr; + allocated_header->prev = 0; + allocated_header->next = 0; + // create another free slot if remaining size is big enough + uint64_t order = frame_ptr->order; + uint64_t total_size = (1 << order) * 4 * kb; + int64_t free_size = total_size - allocated_size - align_up(sizeof(dma_header), 8); + // printf("order :"); + // uart_int(order); + // printf("\n"); + // printf("total_size :"); + // uart_int(total_size); + // printf("\n"); + // printf("free_size :"); + // uart_int(free_size); + // printf("\n"); + if (free_size > 0) { + dma_header *new_header = (dma_header *)(addr + allocated_size); + new_header->total_size = total_size - allocated_size; + new_header->used_size = 0; + new_header->is_allocated = 0; + new_header->frame_ptr = frame_ptr; + new_header->prev = 0; + new_header->next = free_dma_list; + if (free_dma_list) free_dma_list->prev = new_header; + free_dma_list = new_header; + } else { + allocated_header->total_size = total_size; + } + return (void *)(addr + align_up(sizeof(dma_header), 8)); + } + return 0; +} + +void free(void *ptr) { + uint64_t target_addr = (uint64_t)ptr - align_up(sizeof(dma_header), 8); + dma_header *target_header = (dma_header *)target_addr; + target_header->used_size = 0; + target_header->is_allocated = 0; + target_header->prev = 0; + target_header->next = free_dma_list; + if (free_dma_list) free_dma_list->prev = target_header; + free_dma_list = target_header; + + // uart_hex((uint64_t)ptr); + // printf("\n"); + // uart_hex(target_addr); + // printf("\n"); + + page_frame *frame_ptr = target_header->frame_ptr; + uint64_t base_addr = frame_ptr->addr; + uint64_t order = frame_ptr->order; + uint64_t total_frame_size = (1 << order) * 4 * kb; + uint64_t boundary = base_addr + total_frame_size; + + // uart_hex(base_addr); + // printf("\n"); + // uart_hex(total_size); + // printf("\n"); + + // merge next slot if it is free + uint64_t next_addr = target_addr + target_header->total_size; + dma_header *next_header = (dma_header *)next_addr; + if (next_addr < boundary && !next_header->is_allocated) { + if (next_header->prev) next_header->prev->next = next_header->next; + if (next_header->next) next_header->next->prev = next_header->prev; + if (free_dma_list == next_header) free_dma_list = next_header->next; + next_header->prev = 0; + next_header->next = 0; + target_header->total_size += next_header->total_size; + } + // uart_int(target_header->total_size); + // printf("\n"); + // print_dma_list(); + + // merge previous slot if it is free + uint64_t current_addr = base_addr; + while (current_addr < boundary) { + dma_header *header = (dma_header *)current_addr; + uint64_t next_addr = current_addr + header->total_size; + // uart_hex(current_addr); + // printf("\n"); + // uart_hex(next_addr); + // printf("\n"); + if (next_addr == target_addr) { + if (!header->is_allocated) { + header->total_size += target_header->total_size; + // uart_int(header->total_size); + // printf("\n"); + if (target_header->prev) + target_header->prev->next = target_header->next; + if (target_header->next) + target_header->next->prev = target_header->prev; + if (free_dma_list == target_header) free_dma_list = target_header->next; + target_header->prev = 0; + target_header->next = 0; + } + break; + } + current_addr = next_addr; + } + + // free page frame if all slots are free + dma_header *base_header = (dma_header *)base_addr; + if (base_header->total_size == total_frame_size) { + if (base_header->prev) base_header->prev->next = base_header->next; + if (base_header->next) base_header->next->prev = base_header->prev; + if (free_dma_list == base_header) free_dma_list = base_header->next; + base_header->prev = 0; + base_header->next = 0; + buddy_free(frame_ptr); + } +} + +void print_dma_list() { + printf("========================\n"); + printf("Free DMA slots: \n"); + for (dma_header *cur = free_dma_list; cur; cur = cur->next) { + printf("size: "); + uart_int(cur->total_size - align_up(sizeof(dma_header), 8)); + printf(", frame index: "); + uart_int(cur->frame_ptr->id); + printf("\n"); + } + printf("========================\n"); +} diff --git a/lab8/kernel/src/cpio.c b/lab8/kernel/src/cpio.c new file mode 100644 index 000000000..20badd688 --- /dev/null +++ b/lab8/kernel/src/cpio.c @@ -0,0 +1,273 @@ +#include "cpio.h" +#include "printf.h" +#include "string.h" +#include "utils.h" +#include "vfs.h" +#include "alloc.h" + +void cpio_ls() { + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + printf("%s ", pathname); + + ptr = align_up(ptr + namesize, 4); + ptr = align_up(ptr + filesize, 4); + } + printf("\n"); +} + +void cpio_cat(char *pathname_to_cat) { + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + + ptr = align_up(ptr + namesize, 4); + if (strcmp(pathname, pathname_to_cat) == 0) { + char *content = (char *)ptr; + for (unsigned long long i = 0; i < filesize; i++) { + printf("%c", content[i]); + } + printf("\n"); + return; + } + ptr = align_up(ptr + filesize, 4); + } + printf("No such file\n"); +} + +uint32_t cpio_load_user_program(const char *target_program, + uint64_t target_addr) { + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + + ptr = align_up(ptr + namesize, 4); + if (strcmp(pathname, target_program) == 0) { + char *content = (char *)ptr; + char *target_content = (char *)target_addr; + for (unsigned long long i = 0; i < filesize; i++) { + target_content[i] = content[i]; + } + return filesize; + } + ptr = align_up(ptr + filesize, 4); + } + printf("No such file\n"); + return 0; +} + +void cpio_populate_rootfs() { + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + printf("%s %d\n", pathname, filesize); + + ptr = align_up(ptr + namesize, 4); + struct file* file = vfs_open(pathname, O_CREAT); + if (file) { + vfs_write(file, (const char *)ptr, filesize); + vfs_close(file); + } + ptr = align_up(ptr + filesize, 4); + } +} + +// cpiofs +void cpiofs_init() { + cpiofs_v_ops = + (struct vnode_operations*)malloc(sizeof(struct vnode_operations)); + cpiofs_v_ops->lookup = cpiofs_lookup; + cpiofs_v_ops->create = cpiofs_create; + cpiofs_v_ops->set_parent = cpiofs_set_parent; + cpiofs_f_ops = (struct file_operations*)malloc(sizeof(struct file_operations)); + cpiofs_f_ops->write = cpiofs_write; + cpiofs_f_ops->read = cpiofs_read; + cpiofs_f_ops->list = cpiofs_list; +} + +int _cpiofs_create(struct vnode* dir_node, struct cpiofs_file* file, + const char* component_name, FILE_TYPE type) { + + for (int i = 0; i < MAX_FILES_IN_DIR; i++) { + struct cpiofs_fentry* fentry = + ((struct cpiofs_fentry*)dir_node->internal)->child[i]; + if (fentry->type == FILE_NONE) { + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = 0; + vnode->v_ops = dir_node->v_ops; + vnode->f_ops = dir_node->f_ops; + vnode->internal = fentry; + cpiofs_set_fentry(fentry, component_name, file, type, vnode); + // *target = fentry -> vnode; + return 1; + } + } + return -1; +} + +void cpiofs_set_fentry(struct cpiofs_fentry* fentry, const char* component_name, + struct cpiofs_file* file, FILE_TYPE type, struct vnode* vnode) { + strcpy(fentry->name, component_name); + fentry->vnode = vnode; + fentry->type = type; + fentry->file = file; + + if (fentry->type == FILE_DIRECTORY) { + for (int i = 0; i < MAX_FILES_IN_DIR; ++i) { + fentry->child[i] = + (struct cpiofs_fentry*)malloc(sizeof(struct cpiofs_fentry)); + fentry->child[i]->name[0] = 0; + fentry->child[i]->type = FILE_NONE; + fentry->child[i]->parent_vnode = vnode; + } + fentry->file->size = CPIOFS_BUF_SIZE; + } +} + +int cpiofs_setup_mount(struct filesystem* fs, struct mount* mount) { + struct cpiofs_fentry* root_fentry = + (struct cpiofs_fentry*)malloc(sizeof(struct cpiofs_fentry)); + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = mount; + vnode->v_ops = cpiofs_v_ops; + vnode->f_ops = cpiofs_f_ops; + vnode->internal = (void*)root_fentry; + root_fentry->parent_vnode = 0; + cpiofs_set_fentry(root_fentry, "/", 0 , FILE_DIRECTORY, vnode); + mount->fs = fs; + mount->root = vnode; + + // scan cpio + unsigned long long ptr = RAMFS_ADDR; + cpio_newc_header *header; + char *pathname; + + while (1) { + header = (cpio_newc_header *)ptr; + unsigned long long namesize = hex2int(header->c_namesize, 8); + unsigned long long filesize = hex2int(header->c_filesize, 8); + + ptr += sizeof(cpio_newc_header); + pathname = (char *)ptr; + // the end is indicated by a special record with pathname "TRAILER!!!" + if (strcmp(pathname, CPIO_END) == 0) break; + // printf("%s %d\n", pathname, filesize); + + ptr = align_up(ptr + namesize, 4); + + struct cpiofs_file* file = (struct cpiofs_file*)malloc(sizeof(struct cpiofs_file)); + file->buffer = (char *)ptr; + file->size = filesize; + _cpiofs_create(mount->root , file, pathname, FILE_REGULAR); + + ptr = align_up(ptr + filesize, 4); + } + return 1; +} + +int cpiofs_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name) { + // printf("[lookup] %s\n", component_name); + struct cpiofs_fentry* fentry = (struct cpiofs_fentry*)dir_node->internal; + if (fentry->type != FILE_DIRECTORY) return 0; + + if (!strcmp(component_name, ".")) { + *target = fentry->vnode; + return 1; + } + if (!strcmp(component_name, "..")) { + if (!fentry->parent_vnode) return 0; + *target = fentry->parent_vnode; + return 1; + } + + for (int i = 0; i < MAX_FILES_IN_DIR; i++) { + fentry = ((struct cpiofs_fentry*)dir_node->internal)->child[i]; + if (!strcmp(fentry->name, component_name)) { + *target = fentry->vnode; + return 1; + } + } + return 0; +} + +int cpiofs_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type) { + printf("[ERROR] Can't create, R_ONLY\n"); + return -1; +} + +int cpiofs_set_parent(struct vnode* child_node, struct vnode* parent_vnode) { + struct cpiofs_fentry* fentry = (struct cpiofs_fentry*)child_node->internal; + fentry->parent_vnode = parent_vnode; + return 1; +} + +int cpiofs_write(struct file* file, const void* buf, size_t len) { + printf("[ERROR] Can't write, R_ONLY\n"); + return -1; +} + +int cpiofs_read(struct file* file, void* buf, size_t len) { + size_t read_len = 0; + struct cpiofs_fentry* fentry = (struct cpiofs_fentry*)file->vnode->internal; + for (size_t i = 0; i < len; i++) { + ((char*)buf)[i] = fentry->file->buffer[file->f_pos++]; + read_len++; + if (read_len == fentry->file->size) { + break; + } + } + return read_len; +} + +int cpiofs_list(struct file* file, void* buf, int index) { + struct cpiofs_fentry* fentry = (struct cpiofs_fentry*)file->vnode->internal; + if (fentry->type != FILE_DIRECTORY) return -1; + if (index >= MAX_FILES_IN_DIR) return -1; + + if (fentry->child[index]->type == FILE_NONE) return 0; + strcpy((char*)buf, fentry->child[index]->name); + return fentry->child[index]->file->size; +} \ No newline at end of file diff --git a/lab8/kernel/src/delays.c b/lab8/kernel/src/delays.c new file mode 100644 index 000000000..aba77264d --- /dev/null +++ b/lab8/kernel/src/delays.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" + +#define SYSTMR_LO ((volatile unsigned int*)(MMIO_BASE+0x00003004)) +#define SYSTMR_HI ((volatile unsigned int*)(MMIO_BASE+0x00003008)) + +/** + * Wait N CPU cycles (ARM CPU only) + */ +void wait_cycles(unsigned int n) +{ + if(n) while(n--) { asm volatile("nop"); } +} + +/** + * Wait N microsec (ARM CPU only) + */ +void wait_msec(unsigned int n) +{ + register unsigned long f, t, r; + // get the current counter frequency + asm volatile ("mrs %0, cntfrq_el0" : "=r"(f)); + // read the current counter + asm volatile ("mrs %0, cntpct_el0" : "=r"(t)); + // calculate expire value for counter + t+=((f/1000)*n)/1000; + do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(rlookup = device_lookup; + device_v_ops->create = device_create; + device_v_ops->set_parent = device_set_parent; + device_f_ops = (struct file_operations*)malloc(sizeof(struct file_operations)); + device_f_ops->write = device_write; + device_f_ops->read = device_read; + // device_f_ops->list = device_list; +} + +void uartfs_init() { + uartfs_v_ops = + (struct vnode_operations*)malloc(sizeof(struct vnode_operations)); + uartfs_v_ops->lookup = device_lookup; + uartfs_v_ops->create = device_create; + uartfs_v_ops->set_parent = device_set_parent; + uartfs_f_ops = (struct file_operations*)malloc(sizeof(struct file_operations)); + uartfs_f_ops->write = uartfs_write; + uartfs_f_ops->read = uartfs_read; + // uartfs_f_ops->list = device_list; +} + +void device_init() { + root_init(); + uartfs_init(); +} + +void device_set_fentry(struct device_fentry* fentry, const char* component_name, + struct vnode* vnode, DEV_TYPE type) { + // printf("[device_set_fentry]\n"); + strcpy(fentry->name, component_name); + fentry->vnode = vnode; + fentry->type = type; + + if (fentry->type == DEV_ROOT) { + for (int i = 0; i < MAX_DEVICE_IN_DIR; ++i) { + fentry->child[i] = + (struct device_fentry*)malloc(sizeof(struct device_fentry)); + fentry->child[i]->name[0] = 0; + fentry->child[i]->type = DEV_NONE; + fentry->child[i]->parent_vnode = vnode; + } + } +} + +int device_setup_mount(struct filesystem* fs, struct mount* mount) { + // setup cpio root node + struct device_fentry* root_fentry = + (struct device_fentry*)malloc(sizeof(struct device_fentry)); + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode));; + vnode->mount = mount; + vnode->v_ops = device_v_ops; + vnode->f_ops = device_f_ops; + vnode->internal = (void*)root_fentry; + root_fentry->parent_vnode = 0; + device_set_fentry(root_fentry, "/", vnode, DEV_ROOT); + mount->fs = fs; + mount->root = vnode; + + // create device vnode + _device_create(mount->root, "uart", DEV_UART); + + return 1; +} + +int device_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name) { + + // printf("[device_lookup] %s\n", component_name); + struct device_fentry* fentry = (struct device_fentry*)dir_node->internal; + if (fentry->type != DEV_ROOT) return 0; + + if (!strcmp(component_name, ".")) { + //printf("[device_lookup] .\n"); + *target = fentry->vnode; + return 1; + } + if (!strcmp(component_name, "..")) { + //printf("[device_lookup] ..\n"); + if (!fentry->parent_vnode) return 0; + *target = fentry->parent_vnode; + return 1; + } + + for (int i = 0; i < MAX_DEVICE_IN_DIR; i++) { + fentry = ((struct device_fentry*)dir_node->internal)->child[i]; + // printf("[device_lookup] %s\n", fentry->name); + if (!strcmp(fentry->name, component_name)) { + *target = fentry->vnode; + return 1; + } + } + return 0; +} + +int _device_create(struct vnode* dir_node, + const char* component_name, DEV_TYPE type) { + + for (int i = 0; i < MAX_DEVICE_IN_DIR; i++) { + struct device_fentry* fentry = + ((struct device_fentry*)dir_node->internal)->child[i]; + if (fentry->type == DEV_NONE) { + + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = 0; + if(type == DEV_UART){ + vnode->v_ops = uartfs_v_ops; + vnode->f_ops = uartfs_f_ops; + vnode->internal = fentry; + device_set_fentry(fentry, component_name, vnode, type); + return 1; + } + } + } + return -1; +} + +void device_list(struct vnode* dir_node) { + printf("[device_list]: listing dir: %s\n", ((struct device_fentry*)dir_node->internal)->name); + for (int i = 0; i < MAX_DEVICE_IN_DIR; i++) { + struct device_fentry* fentry = + ((struct device_fentry*)dir_node->internal)->child[i]; + if (fentry->type != DEV_NONE) { + printf("[type]: %d, [name]: %s\n", fentry->type, fentry->name); + } + } + printf("\n"); +} + +int device_set_parent(struct vnode* child_node, struct vnode* parent_vnode) { + struct device_fentry* fentry = (struct device_fentry*)child_node->internal; + fentry->parent_vnode = parent_vnode; + return 1; +} + +int device_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type) { + printf("[device_create] no create function for /dev\n"); + return -1; +} + +int device_write(struct file* file, const void* buf, size_t len) { + /* todo */ + printf("[device_write] no write function for /dev\n"); + return -1; +} + +int device_read(struct file* file, void* buf, size_t len) { + printf("[device_read] no read function for /dev\n"); + return -1; +} + + + +// uart read write functions + +int uartfs_read(struct file* file, void* buf, size_t len) { + size_t read_len = 0; + struct device_fentry* fentry = (struct device_fentry*)file->vnode->internal; + for (size_t i = 0; i < len; i++) { + if(fentry->type == DEV_UART){ + ((char*)buf)[i] = uart_getc(); + } + read_len++; + } + return read_len; +} + +int uartfs_write(struct file* file, const void* buf, size_t len) { + for (size_t i = 0; i < len; i++) { + uart_send( ((char*)buf)[i] ); + } + return len; +} diff --git a/lab8/kernel/src/dtb.c b/lab8/kernel/src/dtb.c new file mode 100644 index 000000000..e9461b191 --- /dev/null +++ b/lab8/kernel/src/dtb.c @@ -0,0 +1,252 @@ +#include "dtb.h" + +#include "printf.h" +#include "string.h" +#include "utils.h" + +void mailbox_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + if (check_compatibility(struct_addr, strings_addr, "brcm,bcm2835-mbox") == 0) + return; + print_node(struct_addr, strings_addr, depth); +} + +void gpio_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + if (check_compatibility(struct_addr, strings_addr, "brcm,bcm2835-gpio") == 0) + return; + print_node(struct_addr, strings_addr, depth); +} + +void rtx3080ti_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + if (check_compatibility(struct_addr, strings_addr, "rtx3080ti") == 0) return; + print_node(struct_addr, strings_addr, depth); +} + +void default_probe(uint64_t struct_addr, uint64_t strings_addr, int depth) { + print_node(struct_addr, strings_addr, depth); +} + +int check_compatibility(uint64_t struct_addr, uint64_t strings_addr, + char *compatible_name) { + char *name = (char *)(struct_addr); + struct_addr += strlen(name) + 1; + struct_addr = align_up(struct_addr, 4); + + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_PROP) { + uint32_t len = dtb_read_int(struct_addr); + len = be2le(len); + struct_addr += 4; + uint32_t nameoff = dtb_read_int(struct_addr); + nameoff = be2le(nameoff); + struct_addr += 4; + char *property = (char *)(strings_addr + nameoff); + + if (strcmp(property, "compatible") == 0) { + uint64_t end = struct_addr + len; + while (struct_addr < end) { + char *string = (char *)struct_addr; + struct_addr += strlen(string) + 1; + if (strcmp(string, compatible_name) == 0) return 1; + } + return 0; + } else { + struct_addr += len; + struct_addr = align_up(struct_addr, 4); + } + } else if (token == FDT_NOP) { + continue; + } else { + break; + } + } + return 0; +} + +void dtb_print(int all) { + uint64_t dtb_addr = *((uint64_t *)0x9000000); + printf("dtb_addr = %x\n",dtb_addr); + fdt_header *header = (fdt_header *)dtb_addr; + uint64_t struct_addr = dtb_addr + be2le(header->off_dt_struct); + uint64_t strings_addr = dtb_addr + be2le(header->off_dt_strings); + + if (all) { + dtb_parse(struct_addr, strings_addr, default_probe); + } else { + printf("\ndevice for mailbox driver function: \n"); + dtb_parse(struct_addr, strings_addr, mailbox_probe); + printf("\ndevice for gpio driver function: \n"); + dtb_parse(struct_addr, strings_addr, gpio_probe); + printf("\ndevice for rtx3080ti driver function: \n"); + dtb_parse(struct_addr, strings_addr, rtx3080ti_probe); + } +} + +void dtb_parse(uint64_t struct_addr, uint64_t strings_addr, + void (*callback)(uint64_t, uint64_t, int)) { + int depth = 0; + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + callback(struct_addr, strings_addr, depth); + struct_addr = ignore_current_node(struct_addr, strings_addr); + depth++; + } else if (token == FDT_END_NODE) { + depth--; + } else if (token == FDT_NOP) { + continue; + } else if (token == FDT_END) { + break; + } + } +} + +uint64_t ignore_current_node(uint64_t struct_addr, uint64_t strings_addr) { + char *name = (char *)(struct_addr); + struct_addr += strlen(name) + 1; + struct_addr = align_up(struct_addr, 4); + + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_END_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_PROP) { + uint32_t len = dtb_read_int(struct_addr); + len = be2le(len); + struct_addr += 4; + uint32_t nameoff = dtb_read_int(struct_addr); + nameoff = be2le(nameoff); + struct_addr += 4; + struct_addr += len; + struct_addr = align_up(struct_addr, 4); + } else if (token == FDT_NOP) { + continue; + } + } + return struct_addr; +} + +uint64_t print_node(uint64_t struct_addr, uint64_t strings_addr, int depth) { + char *name = (char *)(struct_addr); + struct_addr += strlen(name) + 1; + struct_addr = align_up(struct_addr, 4); + for (int i = 0; i < depth; i++) printf(" "); + printf("node: %s\n", name); + + while (1) { + uint32_t token = dtb_read_int(struct_addr); + token = be2le(token); + struct_addr += 4; + + if (token == FDT_BEGIN_NODE) { + break; + } else if (token == FDT_END_NODE) { + struct_addr -= 4; + break; + } else if (token == FDT_PROP) { + struct_addr = print_property(struct_addr, strings_addr, depth + 1); + } else if (token == FDT_NOP) { + continue; + } + } + return struct_addr; +} + +uint64_t print_property(uint64_t struct_addr, uint64_t strings_addr, + int depth) { + uint32_t len = dtb_read_int(struct_addr); + len = be2le(len); + struct_addr += 4; + uint32_t nameoff = dtb_read_int(struct_addr); + nameoff = be2le(nameoff); + struct_addr += 4; + char *property = (char *)(strings_addr + nameoff); + + int value_type = 0; + char *is_u32[] = {"phandle", "#address-cells", "#size-cells", "virtual-reg", + "interrupt-parent"}; + char *is_string[] = {"compatible", "model", "status", "name", "device_type"}; + + for (int i = 0; i < sizeof(is_u32) / sizeof(is_u32[0]); i++) { + if (strcmp(property, is_u32[i]) == 0) { + value_type = 1; + break; + } + } + for (int i = 0; i < sizeof(is_string) / sizeof(is_string[0]); i++) { + if (strcmp(property, is_string[i]) == 0) { + value_type = 2; + break; + } + } + + for (int i = 0; i < depth; i++) printf(" "); + printf("%s = ", property); + + // hex, e.g. <0x4600 0x100> + if (value_type == 0) { + int count = 0; + printf("<"); + for (uint32_t i = 0; i < len; i += 4) { + if (count > 0) printf(" "); + count++; + uint32_t num = dtb_read_int(struct_addr); + num = be2le(num); + struct_addr += 4; + printf("0x%x", num); + } + printf(">"); + } + // int, e.g. <1> + if (value_type == 1) { + uint32_t num = dtb_read_int(struct_addr); + num = be2le(num); + struct_addr += 4; + printf("<%d>", num); + } + // string or string list, e.g. "fsl,MPC8349EMITX" or "fsl,mpc8641", "ns16550" + if (value_type == 2) { + int count = 0; + uint64_t end = struct_addr + len; + + while (struct_addr < end) { + if (count > 0) printf(", "); + count++; + char *string = (char *)struct_addr; + struct_addr += strlen(string) + 1; + printf("\"%s\"", string); + } + } + printf("\n"); + + struct_addr = align_up(struct_addr, 4); + return struct_addr; +} + +uint32_t dtb_read_int(uint64_t addr_ptr) { + char *base = (char *)(addr_ptr); + uint32_t value = 0; + for (int i = 3; i >= 0; i--) { + value = (value << 8) | (*(base + i) & 0xFF); + } + return value; +} + +// char *dtb_read_string(uint64_t addr_ptr) { +// char *base = (char *)(addr_ptr); +// char *string_start = base; +// return string_start; +// } \ No newline at end of file diff --git a/lab8/kernel/src/exception.S b/lab8/kernel/src/exception.S new file mode 100644 index 000000000..9ef00764b --- /dev/null +++ b/lab8/kernel/src/exception.S @@ -0,0 +1,127 @@ +// save general registers to stack +.macro save_reg + sub sp, sp, 32 * 9 + stp x0, x1, [sp, 16 * 0] + stp x2, x3, [sp, 16 * 1] + stp x4, x5, [sp, 16 * 2] + stp x6, x7, [sp, 16 * 3] + stp x8, x9, [sp, 16 * 4] + stp x10, x11, [sp, 16 * 5] + stp x12, x13, [sp, 16 * 6] + stp x14, x15, [sp, 16 * 7] + stp x16, x17, [sp, 16 * 8] + stp x18, x19, [sp, 16 * 9] + stp x20, x21, [sp, 16 * 10] + stp x22, x23, [sp, 16 * 11] + stp x24, x25, [sp, 16 * 12] + stp x26, x27, [sp, 16 * 13] + stp x28, x29, [sp, 16 * 14] + //str x30, [sp, 16 * 15] + mrs x10, spsr_el1 + mrs x11, elr_el1 + mrs x12, sp_el0 + stp x30, x10, [sp, 16 * 15] + stp x11, x12, [sp, 16 * 16] +.endm + +// load general registers from stack +.macro load_reg + ldp x30, x10, [sp, 16 * 15] + ldp x11, x12, [sp, 16 * 16] + msr spsr_el1, x10 + msr elr_el1, x11 + msr sp_el0, x12 + ldp x0, x1, [sp, 16 * 0] + ldp x2, x3, [sp, 16 * 1] + ldp x4, x5, [sp, 16 * 2] + ldp x6, x7, [sp, 16 * 3] + ldp x8, x9, [sp, 16 * 4] + ldp x10, x11, [sp, 16 * 5] + ldp x12, x13, [sp, 16 * 6] + ldp x14, x15, [sp, 16 * 7] + ldp x16, x17, [sp, 16 * 8] + ldp x18, x19, [sp, 16 * 9] + ldp x20, x21, [sp, 16 * 10] + ldp x22, x23, [sp, 16 * 11] + ldp x24, x25, [sp, 16 * 12] + ldp x26, x27, [sp, 16 * 13] + ldp x28, x29, [sp, 16 * 14] + //ldr x30, [sp, 16 * 15] + //ldp x30, x10, [sp, 16 * 15] + //ldp x11, x12, [sp, 16 * 16] + //msr spsr_el1, x10 + //msr elr_el1, x11 + //msr sp_el0, x12 + add sp, sp, 32 * 9 +.endm + +.align 11 // vector table should be aligned to 0x800 +.global exception_vector_table +exception_vector_table: + b _default_handler // branch to a handler function. + .align 7 // entry size is 0x80, .align will pad 0 + b _default_handler + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + + b _sync_handler_currentEL_ELx + .align 7 + b _irq_handler_currentEL_ELx + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + + b _sync_handler_lowerEL_64 + .align 7 + b _irq_handler_lowerEL_64 + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + + b _default_handler + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + b _default_handler + .align 7 + +_sync_handler_currentEL_ELx: + save_reg + bl sync_handler_currentEL_ELx // exception.c + load_reg + eret + +_sync_handler_lowerEL_64: + save_reg + //mrs x0, sp_el0 + mov x0, sp + bl sync_handler_lowerEL_64 // exception.c + load_reg + eret + +_irq_handler_currentEL_ELx: + save_reg + bl irq_handler_currentEL_ELx // exception.c + load_reg + eret + +_irq_handler_lowerEL_64: + save_reg + bl irq_handler_lowerEL_64 // exception.c + load_reg + eret + +_default_handler: + save_reg + bl default_handler // exception.c + load_reg + eret \ No newline at end of file diff --git a/lab8/kernel/src/exception.c b/lab8/kernel/src/exception.c new file mode 100644 index 000000000..5f3b3f457 --- /dev/null +++ b/lab8/kernel/src/exception.c @@ -0,0 +1,165 @@ +#include "exception.h" +#include "uart.h" +#include "utils.h" +#include "timer.h" +#include "string.h" +#include "thread.h" +#include "printf.h" +#include "mbox.h" +#include "vfs.h" + +int count = 0; + +void enable_interrupt() { asm volatile("msr DAIFClr, 0xf"); } + +void disable_interrupt() { asm volatile("msr DAIFSet, 0xf"); } + +void sync_handler_currentEL_ELx() { + printf("[sync_handler_currentEL_ELx]\n"); + + uint64_t spsr_el1, elr_el1, esr_el1; + asm volatile("mrs %0, spsr_el1" : "=r"(spsr_el1)); + asm volatile("mrs %0, elr_el1" : "=r"(elr_el1)); + asm volatile("mrs %0, esr_el1" : "=r"(esr_el1)); + while(1); +} + +void sync_handler_lowerEL_64(uint64_t sp) { + // printf("sync_handler_lowerEL_64 sp : %x\n",sp); + uint64_t spsr_el1, elr_el1, esr_el1; + asm volatile("mrs %0, spsr_el1" : "=r"(spsr_el1)); + asm volatile("mrs %0, elr_el1" : "=r"(elr_el1)); + asm volatile("mrs %0, esr_el1" : "=r"(esr_el1)); + // printf("sync, SPSR_EL1: 0x%08x\n", spsr_el1); + // printf("ELR_EL1: 0x%08x\n", elr_el1); + // printf("ESR_EL1: 0x%08x\n", esr_el1); + + uint32_t ec = (esr_el1 >> 26) & 0x3f; + // printf("EC: %x\n", ec); + if (ec == 0b010101) { // SVC instruction + // printf("pid = %d, ",get_current()->pid); + uint64_t iss; + asm volatile("mov %0, x8" : "=r"(iss)); + // printf("syscall number: %d\n", iss); + trap_frame_t *trap_frame = (trap_frame_t *)sp; + + if (iss == 0) { // getpid + uint32_t pid = get_current()->pid; + trap_frame->x[0] = pid; + } else if (iss == 1) { // uartread + // printf("[read]\n"); + disable_uart_interrupt(); + enable_interrupt(); + char *str = (char *)(trap_frame->x[0]); + uint32_t size = (uint32_t)(trap_frame->x[1]); + size = uart_gets(str, size); + trap_frame->x[0] = size; + } else if (iss == 2) { // uartwrite + // printf("[write]\n"); + char *str = (char *)(trap_frame->x[0]); + trap_frame->x[0] = uart_write(str,trap_frame->x[1]); + } else if (iss == 3) { // exec + const char *program_name = (const char *)trap_frame->x[0]; + const char **argv = (const char **)trap_frame->x[1]; + exec(program_name, argv); + } else if (iss == 4) { // fork + // printf("[fork]\n"); + fork(sp); + } else if (iss == 5) { // exit + exit(); + } else if (iss == 6) { // mbox_call + // printf("[mbox_call]\n"); + trap_frame->x[0] = mbox_call(trap_frame->x[0],(unsigned int *)trap_frame->x[1]); + } else if (iss == 7) { // kill + kill((int)trap_frame->x[0]); + } //vfs + else if (iss == 11) { // open + printf("[open]%s\n",(const char *)trap_frame->x[0]); + struct file* file = vfs_open((const char *)trap_frame->x[0],trap_frame->x[1]); + int fd = thread_register_fd(file); + printf("[open]fd :%d\n",fd); + + trap_frame->x[0] = fd; + + } else if (iss == 12) { // close + printf("[close]fd =%d\n",trap_frame->x[0]); + struct file* file = thread_get_file(trap_frame->x[0]); + vfs_close(file); + + } else if (iss == 13) { // write + // remember to return read size or error code + printf("[write]\n"); + printf("[write]fd =%d\n",trap_frame->x[0]); + printf("[write]write_buf =%s\n",trap_frame->x[1]); + printf("[write]size =%d\n",trap_frame->x[2]); + struct file* file = thread_get_file(trap_frame->x[0]); + trap_frame->x[0] = vfs_write(file, (const void *)trap_frame->x[1], trap_frame->x[2]); + + } else if (iss == 14) { // read + // remember to return read size or error code + printf("[read]\n"); + printf("[read]id =%d\n",trap_frame->x[0]); + printf("[read]read_buf =%s\n",trap_frame->x[1]); + printf("[read]size =%d\n",trap_frame->x[2]); + struct file* file = thread_get_file(trap_frame->x[0]); + trap_frame->x[0] = vfs_read(file, (void *)trap_frame->x[1], trap_frame->x[2]); + printf("[read][after] read_buf =%s\n",trap_frame->x[1]); + + } else if (iss == 15) { // mkdir + // you can ignore mode, since there is no access control + printf("[mkdir]%s\n",(const char *)trap_frame->x[0]); + trap_frame->x[0] = vfs_mkdir((const char *)trap_frame->x[0]); + + } else if (iss == 16) { // mount + // you can ignore arguments other than target (where to mount) and filesystem (fs name) + const char *device = (const char *)trap_frame->x[0]; + const char *mountpoint = (const char *)trap_frame->x[1]; + const char *filesystem = (const char *)trap_frame->x[2]; + printf("[mount]mountpoint %s\n", mountpoint); + printf("[mount]filesystem %s\n", filesystem); + + int result = vfs_mount(device, mountpoint, filesystem); + trap_frame->x[0] = result; + + } else if (iss == 17) { // chdir + const char *pathname = (const char *)trap_frame->x[0]; + printf("[chdir]%s\n", pathname); + + int result = vfs_chdir(pathname); + trap_frame->x[0] = result; + } + } +} + + +void irq_handler_currentEL_ELx() { + // printf("====irq_handler_currentEL_ELx=====\n"); + + disable_interrupt(); + uint32_t is_uart = (*IRQ_PENDING_1 & AUX_IRQ); + uint32_t is_core_timer = (*CORE0_INTERRUPT_SOURCE & 0x2); + + if (is_uart) { + uart_handler(); + } else if (is_core_timer) { + core_timer_handler_lowerEL_64(); + } + enable_interrupt(); +} + +void irq_handler_lowerEL_64() { + // printf("====irq_handler_lowerEL_64=====\n"); + disable_interrupt(); + uint32_t is_uart = (*IRQ_PENDING_1 & AUX_IRQ); + uint32_t is_core_timer = (*CORE0_INTERRUPT_SOURCE & 0x2); + + if (is_uart) { + uart_handler(); + } else if (is_core_timer) { + core_timer_handler_lowerEL_64(); + } + enable_interrupt(); +} + + +void default_handler() { uart_puts("===== default handler =====\n"); } diff --git a/lab8/kernel/src/fatfs.c b/lab8/kernel/src/fatfs.c new file mode 100644 index 000000000..7fb7e25c8 --- /dev/null +++ b/lab8/kernel/src/fatfs.c @@ -0,0 +1,328 @@ +#include "fatfs.h" + +#include "alloc.h" +#include "printf.h" +#include "sdhost.h" +#include "string.h" +#include "vfs.h" + +int get_starting_sector(int cluster) { + return (cluster - 2) * fat_boot_sector->sectors_per_cluster + + data_starting_sector; +} + +void fatfs_init() { + fatfs_v_ops = + (struct vnode_operations*)malloc(sizeof(struct vnode_operations)); + fatfs_v_ops->lookup = fatfs_lookup; + fatfs_v_ops->set_parent = fatfs_set_parent; + fatfs_v_ops->create = fatfs_create; + + fatfs_f_ops = (struct file_operations*)malloc(sizeof(struct file_operations)); + fatfs_f_ops->write = fatfs_write; + fatfs_f_ops->read = fatfs_read; + sd_init(); +} + +void fatfs_set_directory(struct fatfs_fentry* fentry, + struct fatfs_dentry* dentry) { + for (int i = 0; i < MAX_FILES_IN_DIR; ++i) { + int weird = 0; + + for (int j = 0; j < 8; j++) { + // handle weird file + if ((dentry + i)->filename[j] == 0) { + weird = 1; + // clean it + if(i!=0){ // i don't know why can't clean first dentry in real machine + for(int k = 0 ; k < 11; k++) (dentry + i)->filename[k] = 0; + } + } + } + + if ((dentry + i)->filename[0] && !weird) { + // concate file name + strncpy(fentry->child[i]->name, (dentry + i)->filename, 8); + size_t len = strlen(fentry->child[i]->name); + fentry->child[i]->name_len = len; + if ((dentry + i)->extension[0]) { + *(fentry->child[i]->name + len) = '.'; + strncpy(fentry->child[i]->name + len + 1, (dentry + i)->extension, 3); + } + + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = 0; + vnode->v_ops = fentry->vnode->v_ops; + vnode->f_ops = fentry->vnode->f_ops; + vnode->internal = fentry->child[i]; + int starting_cluster = + ((dentry + i)->cluster_high << 2) + (dentry + i)->cluster_low; + + int buf_size = (dentry + i)->file_size; + fatfs_set_fentry(fentry->child[i], FILE_REGULAR, vnode, starting_cluster, + buf_size); + // printf("num_file = %d\n",i); + // printf("starting_cluster = %d\n",starting_cluster); + // printf("file_size = %d\n", (dentry + i)->file_size); + // printf("%s\n", fentry->child[i]->name); + current_starting_sector = starting_cluster; + } + } + current_starting_sector++; +} + +void list_sd() { + printf("==================================\n"); + + printf("sd files :\n"); + for (int i = 0; i < MAX_FILES_IN_DIR; ++i) { + int weird = 0; + for (int j = 0; j < 11; j++) { + printf("0x%x ", (fat_root_dentry + i)->filename[j]); + } + printf("\n"); + if ((fat_root_dentry + i)->filename[0]) { + printf("num_file = %d, %s, file_size = %d\n", i, (fat_root_dentry + i)->filename, (fat_root_dentry + i)->file_size); + } + } + printf("==================================\n"); + +} + + +void fatfs_set_fentry(struct fatfs_fentry* fentry, FILE_TYPE type, + struct vnode* vnode, int starting_cluster, int buf_size) { + fentry->starting_cluster = starting_cluster; + fentry->vnode = vnode; + fentry->type = type; + fentry->buf = (struct fatfs_buf*)malloc(sizeof(struct fatfs_buf)); + fentry->buf->size = buf_size; + // init buffer + for (int i = 0; i < FATFS_BUF_SIZE; i++) { + fentry->buf->buffer[i] = '\0'; + } + // init child files + if (fentry->type == FILE_DIRECTORY) { + for (int i = 0; i < MAX_FILES_IN_DIR; ++i) { + fentry->child[i] = + (struct fatfs_fentry*)malloc(sizeof(struct fatfs_fentry)); + fentry->child[i]->name[0] = 0; + fentry->child[i]->type = FILE_NONE; + fentry->child[i]->parent_vnode = vnode; + } + } +} + +int fatfs_setup_mount(struct filesystem* fs, struct mount* mount) { + //parse some message from first block + char* mbr = (char*)malloc(BLOCK_SIZE); + readblock(0, mbr); + if (mbr[510] != 0x55 || mbr[511] != 0xAA) { + printf("[fatfs_init] bad magic in MBR\n"); + return 0; + } + + int entry_size = sizeof(struct mbr_partition_entry); + struct mbr_partition_entry* entry = + (struct mbr_partition_entry*)malloc(entry_size); + char* src = (char*)mbr; + char* dst = (char*)entry; + for (int i = 0; i < entry_size; i++) { + // printf("i: %d, 0x%x\n", i, src[MBR_PARTITION_BASE + i]); + dst[i] = src[MBR_PARTITION_BASE + i]; + } + free(mbr); + + printf("\n========== FAT32 init ==========\n"); + // printf("Partition type: 0x%x", entry->partition_type); + // if (entry->partition_type == 0xB) { + // printf(" (FAT32 with CHS addressing)"); + // } + // printf("\nPartition size: %d (sectors)\n", entry->sector_count); + printf("Block index: %d\n", entry->starting_sector); + printf("================================\n\n"); + fat_starting_sector = entry->starting_sector; // 2048 + + // parse some message from fat_starting_sector block + char* fat_boot = (char*)malloc(BLOCK_SIZE); + readblock(fat_starting_sector, fat_boot); + int boot_sector_size = sizeof(struct fatfs_boot_sector); + fat_boot_sector = (struct fatfs_boot_sector*)malloc(boot_sector_size); + src = (char*)fat_boot; + dst = (char*)fat_boot_sector; + for (int i = 0; i < boot_sector_size; i++) { + dst[i] = src[i]; + } + free(fat_boot); + + int root_dir_sectors = 0; // no root directory sector in FAT32 + data_starting_sector = + fat_starting_sector + fat_boot_sector->reserved_sector_count + + fat_boot_sector->fat_count * fat_boot_sector->sectors_per_fat_32 + + root_dir_sectors; + + // printf("fat_starting_sector = %d\n",fat_starting_sector); + // printf("fat_boot_sector->reserved_sector_count = %d\n",fat_boot_sector->reserved_sector_count); + // printf("fat_boot_sector->fat_count = %d\n",fat_boot_sector->fat_count); + // printf("fat_boot_sector->sectors_per_fat_32 = %d\n",fat_boot_sector->sectors_per_fat_32); + // printf("root_dir_sectors = %d\n",root_dir_sectors); + // printf("fat_boot_sector->root_cluster = %d\n",fat_boot_sector->root_cluster); + + root_starting_sector = get_starting_sector(fat_boot_sector->root_cluster); + + // printf("data_starting_sector = %d\n", data_starting_sector); + // printf("root_starting_sector = %d\n", root_starting_sector); + + char* fat_root = (char*)malloc(BLOCK_SIZE); + readblock(root_starting_sector, fat_root); + fat_root_dentry = (struct fatfs_dentry*)fat_root; + + struct fatfs_fentry* root_fentry = + (struct fatfs_fentry*)malloc(sizeof(struct fatfs_fentry)); + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = mount; + vnode->v_ops = fatfs_v_ops; + vnode->f_ops = fatfs_f_ops; + vnode->internal = (void*)root_fentry; + root_fentry->parent_vnode = 0; + fatfs_set_fentry(root_fentry, FILE_DIRECTORY, vnode, + fat_boot_sector->root_cluster, 4096); + fatfs_set_directory(root_fentry, fat_root_dentry); + mount->fs = fs; + mount->root = vnode; + return 1; +} + +int fatfs_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name) { + printf("[lookup] %s\n", component_name); + struct fatfs_fentry* fentry = (struct fatfs_fentry*)dir_node->internal; + if (fentry->type != FILE_DIRECTORY) return 0; + + if (!strcmp(component_name, ".")) { + *target = fentry->vnode; + return 1; + } + if (!strcmp(component_name, "..")) { + if (!fentry->parent_vnode) return 0; + *target = fentry->parent_vnode; + return 1; + } + + for (int i = 0; i < MAX_FILES_IN_DIR; i++) { + fentry = ((struct fatfs_fentry*)dir_node->internal)->child[i]; + if (!strcmp(fentry->name, component_name)) { + *target = fentry->vnode; + return 1; + } + } + return 0; +} + +int fatfs_set_parent(struct vnode* child_node, struct vnode* parent_vnode) { + struct fatfs_fentry* fentry = (struct fatfs_fentry*)child_node->internal; + fentry->parent_vnode = parent_vnode; + return 1; +} + +int fatfs_write(struct file* file, const void* buf, size_t len) { + struct fatfs_fentry* fentry = (struct fatfs_fentry*)file->vnode->internal; + for (size_t i = 0; i < len; i++) { + fentry->buf->buffer[file->f_pos++] = ((char*)buf)[i]; + if (fentry->buf->size < file->f_pos) { + fentry->buf->size = file->f_pos; + } + } + + for (int i = 0; i < MAX_FILES_IN_DIR; i++) { + if (!strncmp((fat_root_dentry + i)->filename, fentry->name, fentry->name_len)) { + (fat_root_dentry + i)->file_size = fentry->buf->size; + printf("new file size: %d\n", (fat_root_dentry + i)->file_size); + } + } + writeblock(root_starting_sector, (char*)fat_root_dentry); + printf("%s\n", fentry->buf->buffer); + + int starting_sector = get_starting_sector(fentry->starting_cluster); + writeblock(starting_sector, fentry->buf->buffer); + + return len; +} + +int fatfs_read(struct file* file, void* buf, size_t len) { + printf("[fatfs_read]\n"); + size_t read_len = 0; + struct fatfs_fentry* fentry = (struct fatfs_fentry*)file->vnode->internal; + int starting_sector = get_starting_sector(fentry->starting_cluster); + // printf("fentry->starting_cluster = %d\n", fentry->starting_cluster); + // printf("starting_sector = %d\n", starting_sector); + readblock(starting_sector, fentry->buf->buffer); + + for (size_t i = 0; i < len; i++) { + ((char*)buf)[i] = fentry->buf->buffer[file->f_pos++]; + read_len++; + if (read_len == fentry->buf->size) { + break; + } + } + return read_len; +} + + +int fatfs_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type) { + for (int i = 0; i < MAX_FILES_IN_DIR; i++) { + struct fatfs_fentry* fentry = + ((struct fatfs_fentry*)dir_node->internal)->child[i]; + if (fentry->type == FILE_NONE) { + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = 0; + vnode->v_ops = dir_node->v_ops; + vnode->f_ops = dir_node->f_ops; + vnode->internal = fentry; + + //assign name and name_len + for(int j = 0; j < 11; j++) fentry->name[j] = ' '; + fentry->name_len = 11; + int fentry_name_cnt = 0; + printf("current_starting_sector = %d\n",current_starting_sector); + for(int dir_idx = 0 ; dir_idx < MAX_FILES_IN_DIR ; dir_idx ++){ + if(!((fat_root_dentry + dir_idx)->filename[0])) { + + // copy FAT_R.TXT file dentry + char * src; + for (int j = 0 ; j < MAX_FILES_IN_DIR ; j++){ + if (!strncmp((fat_root_dentry + j)->filename, "FAT_R", 5)){ + src = (char *)(fat_root_dentry + j); + break; + } + } + char * dst = (char*)(fat_root_dentry + dir_idx); + for(int j = 0; j < sizeof(struct fatfs_dentry); j++) dst[j] = src[j]; + + // parse name & extension + for(int j = 0; j < 11; j++) (fat_root_dentry + dir_idx)->filename[j] = ' '; + int p_idx = 0; + for( p_idx = 0 ; p_idx < 8 ; p_idx++){ + if(component_name[p_idx] == '.') break; + fentry->name[fentry_name_cnt++] = (fat_root_dentry + dir_idx)->filename[p_idx] = component_name[p_idx]; + } + + fentry_name_cnt = 8; + for(int idx = 0 ; idx < 3 ; idx++){ + fentry->name[fentry_name_cnt++] = (fat_root_dentry + dir_idx)->extension[idx] = component_name[++p_idx]; + } + + // deal with cluster + (fat_root_dentry + dir_idx)->cluster_low = current_starting_sector; + writeblock(root_starting_sector, (char*)fat_root_dentry); + break; + } + } + fatfs_set_fentry(fentry, type, vnode, current_starting_sector, 0); + *target = fentry->vnode; + return 1; + } + } + return -1; +} \ No newline at end of file diff --git a/lab8/kernel/src/linker.ld b/lab8/kernel/src/linker.ld new file mode 100644 index 000000000..ef09ab120 --- /dev/null +++ b/lab8/kernel/src/linker.ld @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +SECTIONS +{ + . = 0x80000; + .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) } + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) } + PROVIDE(_data = .); + .data : { *(.data .data.* .gnu.linkonce.d*) } + .bss (NOLOAD) : { + . = ALIGN(16); + __bss_start = .; + *(.bss .bss.*) + *(COMMON) + __bss_end = .; + } + _end = .; + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} +__bss_size = (__bss_end - __bss_start)>>3; \ No newline at end of file diff --git a/lab8/kernel/src/main.c b/lab8/kernel/src/main.c new file mode 100644 index 000000000..3275b2877 --- /dev/null +++ b/lab8/kernel/src/main.c @@ -0,0 +1,32 @@ +#include "uart.h" +#include "string.h" +#include "power.h" +#include "mbox.h" +#include "cpio.h" +#include "timer.h" +#include "exception.h" +#include "alloc.h" +#include "utils.h" +#include "thread.h" +#include "printf.h" +#include "shell.h" +#include "vfs.h" + +// #include "device_tree.h" +void main() +{ + // set up serial console + uart_init(); + buddy_init(); + //welcome message + uart_puts("*****************************\r\n"); + uart_puts("* welcome OSC2022 *\r\n"); + uart_puts("*****************************\r\n"); + timeout_event_init(); + enable_interrupt(); + // thread_init(); + vfs_init(); + thread_init(); + run_shell(); +} + diff --git a/lab8/kernel/src/math.c b/lab8/kernel/src/math.c new file mode 100644 index 000000000..2b89b515c --- /dev/null +++ b/lab8/kernel/src/math.c @@ -0,0 +1,9 @@ +int pow(int base, int exponent) +{ + int result = 1; + for ( ; exponent > 0; exponent--) + { + result = result * base; + } + return result; +} \ No newline at end of file diff --git a/lab8/kernel/src/mbox.c b/lab8/kernel/src/mbox.c new file mode 100644 index 000000000..f0ce82048 --- /dev/null +++ b/lab8/kernel/src/mbox.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" + +/* mailbox message buffer */ +volatile unsigned int __attribute__((aligned(16))) mbox[36]; + +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) +#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) +#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) +#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) +#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) +#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) +#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) +#define MBOX_RESPONSE 0x80000000 +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 + +/** + * Make a mailbox call. Returns 0 on failure, non-zero on success + */ +int mbox_call(unsigned char ch, unsigned int *user_mbox) +{ + unsigned int r = (((unsigned int)((unsigned long)user_mbox)&~0xF) | (ch&0xF)); + /* wait until we can write to the mailbox */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_FULL); + /* write the address of our message to the mailbox with channel identifier */ + *MBOX_WRITE = r; + /* now wait for the response */ + while(1) { + /* is there a response? */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY); + /* is it a response to our message? */ + if(r == *MBOX_READ) + /* is it a valid successful response? */ + return user_mbox[1]==MBOX_RESPONSE; + } + return 0; +} diff --git a/lab8/kernel/src/power.c b/lab8/kernel/src/power.c new file mode 100644 index 000000000..c066b6259 --- /dev/null +++ b/lab8/kernel/src/power.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" +#include "mbox.h" +#include "delays.h" + +#define PM_RSTC ((volatile unsigned int*)(MMIO_BASE+0x0010001c)) +#define PM_RSTS ((volatile unsigned int*)(MMIO_BASE+0x00100020)) +#define PM_WDOG ((volatile unsigned int*)(MMIO_BASE+0x00100024)) +#define PM_WDOG_MAGIC 0x5a000000 +#define PM_RSTC_FULLRST 0x00000020 + +/** + * Shutdown the board + */ +void power_off() +{ + unsigned long r; + + // power off devices one by one + for(r=0;r<16;r++) { + mbox[0]=8*4; + mbox[1]=MBOX_REQUEST; + mbox[2]=MBOX_TAG_SETPOWER; // set power state + mbox[3]=8; + mbox[4]=8; + mbox[5]=(unsigned int)r; // device id + mbox[6]=0; // bit 0: off, bit 1: no wait + mbox[7]=MBOX_TAG_LAST; + mbox_call(MBOX_CH_PROP,mbox); + } + + // power off gpio pins (but not VCC pins) + *GPFSEL0 = 0; *GPFSEL1 = 0; *GPFSEL2 = 0; *GPFSEL3 = 0; *GPFSEL4 = 0; *GPFSEL5 = 0; + *GPPUD = 0; + wait_cycles(150); + *GPPUDCLK0 = 0xffffffff; *GPPUDCLK1 = 0xffffffff; + wait_cycles(150); + *GPPUDCLK0 = 0; *GPPUDCLK1 = 0; // flush GPIO setup + + // power off the SoC (GPU + CPU) + r = *PM_RSTS; r &= ~0xfffffaaa; + r |= 0x555; // partition 63 used to indicate halt + *PM_RSTS = PM_WDOG_MAGIC | r; + *PM_WDOG = PM_WDOG_MAGIC | 10; + *PM_RSTC = PM_WDOG_MAGIC | PM_RSTC_FULLRST; +} + +/** + * Reboot + */ +void reset() +{ + unsigned int r; + // trigger a restart by instructing the GPU to boot from partition 0 + r = *PM_RSTS; r &= ~0xfffffaaa; + *PM_RSTS = PM_WDOG_MAGIC | r; // boot from partition 0 + *PM_WDOG = PM_WDOG_MAGIC | 10; + *PM_RSTC = PM_WDOG_MAGIC | PM_RSTC_FULLRST; +} diff --git a/lab8/kernel/src/printf.c b/lab8/kernel/src/printf.c new file mode 100644 index 000000000..13b92a7b4 --- /dev/null +++ b/lab8/kernel/src/printf.c @@ -0,0 +1,921 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. These routines are thread +// safe and reentrant! +// Use this instead of the bloated standard/newlib printf cause these use +// malloc for printf (and may not be thread safe). +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "printf.h" + + +// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the +// printf_config.h header file +// default: undefined +#ifdef PRINTF_INCLUDE_CONFIG_H +#include "printf_config.h" +#endif + + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +// support for the floating point type (%f) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +// support for exponential floating point notation (%e/%g) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL +#define PRINTF_SUPPORT_EXPONENTIAL +#endif + +// define the default floating point precision +// default: 6 digits +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +// define the largest float suitable to print with %f +// default: 1e9 +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +// support for the long long types (%llu or %p) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +// support for the ptrdiff_t type (%t) +// ptrdiff_t is normally defined in as long or long long type +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + + +// import float.h for DBL_MAX +#if defined(PRINTF_SUPPORT_FLOAT) +#include +#endif + +// my custom implementation of _putchar +#include "uart.h" +void _putchar(char character) { + if (character == '\n') uart_send('\r'); + uart_send(character); +} + + +// output function type +typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); + + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void* arg); + void* arg; +} out_fct_wrap_type; + + +// internal buffer output +static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) +{ + if (idx < maxlen) { + ((char*)buffer)[idx] = character; + } +} + + +// internal null output +static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)character; (void)buffer; (void)idx; (void)maxlen; +} + + +// internal _putchar wrapper +static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)buffer; (void)idx; (void)maxlen; + if (character) { + _putchar(character); + } +} + + +// internal output function wrapper +static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)idx; (void)maxlen; + if (character) { + // buffer is the output fct pointer + ((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg); + } +} + + +// internal secure strlen +// \return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int _strnlen_s(const char* str, size_t maxsize) +{ + const char* s; + for (s = str; *s && maxsize--; ++s); + return (unsigned int)(s - str); +} + + +// internal test if char is a digit (0-9) +// \return true if char is a digit +static inline bool _is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + + +// internal ASCII string to unsigned int conversion +static unsigned int _atoi(const char** str) +{ + unsigned int i = 0U; + while (_is_digit(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + + +// output the specified string in reverse, taking care of any zero-padding +static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) +{ + const size_t start_idx = idx; + + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + + +// internal itoa format +static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) +{ + // pad leading zeros + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + // handle hash + if (flags & FLAGS_HASH) { + if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { + len--; + if (len && (base == 16U)) { + len--; + } + } + if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } + else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } + else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_NTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +// internal itoa for 'long' type +static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} + + +// internal itoa for 'long long' type +#if defined(PRINTF_SUPPORT_LONG_LONG) +static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#endif // PRINTF_SUPPORT_LONG_LONG + + +#if defined(PRINTF_SUPPORT_FLOAT) + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags); +#endif + + +// internal ftoa for fixed decimal floating point +static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + + // powers of 10 + static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + + // test for special values + if (value != value) + return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + // test for very large values + // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad + if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); +#else + return 0U; +#endif + } + + // test for negative + bool negative = false; + if (value < 0) { + negative = true; + value = 0 - value; + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + // limit precision to 9, cause a prec >= 10 can lead to overflow errors + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { + buf[len++] = '0'; + prec--; + } + + int whole = (int)value; + double tmp = (value - whole) * pow10[prec]; + unsigned long frac = (unsigned long)tmp; + diff = tmp - frac; + + if (diff > 0.5) { + ++frac; + // handle rollover, e.g. case 0.99 with prec 1 is 1.0 + if (frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } + else if (diff < 0.5) { + } + else if ((frac == 0U) || (frac & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++frac; + } + + if (prec == 0U) { + diff = value - (double)whole; + if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++whole; + } + } + else { + unsigned int count = prec; + // now do fractional part, as an unsigned number + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(48U + (frac % 10U)); + if (!(frac /= 10U)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + // add decimal + buf[len++] = '.'; + } + } + + // do whole part, number is reversed + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(48 + (whole % 10)); + if (!(whole /= 10)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + // check for NaN and special values + if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { + return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); + } + + // determine the sign + const bool negative = value < 0; + if (negative) { + value = -value; + } + + // default precision + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // determine the decimal exponent + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + union { + uint64_t U; + double F; + } conv; + + conv.F = value; + int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 + conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) + // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 + int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^expval but we want to be sure it won't overflow + exp2 = (int)(expval * 3.321928094887362 + 0.5); + const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = (uint64_t)(exp2 + 1023) << 52U; + // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if (value < conv.F) { + expval--; + conv.F /= 10; + } + + // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters + unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; + + // in "%g" mode, "prec" is the number of *significant figures* not decimals + if (flags & FLAGS_ADAPT_EXP) { + // do we want to fall-back to "%f" mode? + if ((value >= 1e-4) && (value < 1e6)) { + if ((int)prec > expval) { + prec = (unsigned)((int)prec - expval - 1); + } + else { + prec = 0; + } + flags |= FLAGS_PRECISION; // make sure _ftoa respects precision + // no characters in exponent + minwidth = 0U; + expval = 0; + } + else { + // we use one sigfig for the whole part + if ((prec > 0) && (flags & FLAGS_PRECISION)) { + --prec; + } + } + } + + // will everything fit? + unsigned int fwidth = width; + if (width > minwidth) { + // we didn't fall-back so subtract the characters required for the exponent + fwidth -= minwidth; + } else { + // not enough characters, so go back to default sizing + fwidth = 0U; + } + if ((flags & FLAGS_LEFT) && minwidth) { + // if we're padding on the right, DON'T pad the floating part + fwidth = 0U; + } + + // rescale the float value + if (expval) { + value /= conv.F; + } + + // output the floating part + const size_t start_idx = idx; + idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); + + // output the exponent part + if (minwidth) { + // output the exponential symbol + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + // output the exponent value + idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS); + // might need to right-pad spaces + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + + +// internal vsnprintf +static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) +{ + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + // use null output function + out = _out_null; + } + + while (*format) + { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } + else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break; + case '-': flags |= FLAGS_LEFT; format++; n = 1U; break; + case '+': flags |= FLAGS_PLUS; format++; n = 1U; break; + case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break; + case '#': flags |= FLAGS_HASH; format++; n = 1U; break; + default : n = 0U; break; + } + } while (n); + + // evaluate width field + width = 0U; + if (_is_digit(*format)) { + width = _atoi(&format); + } + else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } + else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (_is_digit(*format)) { + precision = _atoi(&format); + } + else if (*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l' : + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h' : + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't' : + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j' : + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z' : + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default : + break; + } + + // evaluate specifier + switch (*format) { + case 'd' : + case 'i' : + case 'u' : + case 'x' : + case 'X' : + case 'o' : + case 'b' : { + // set the base + unsigned int base; + if (*format == 'x' || *format == 'X') { + base = 16U; + } + else if (*format == 'o') { + base = 8U; + } + else if (*format == 'b') { + base = 2U; + } + else { + base = 10U; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + } + else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags); + } + else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); + idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f' : + case 'F' : + if (*format == 'F') flags |= FLAGS_UPPERCASE; + idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + case 'c' : { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's' : { + const char* p = va_arg(va, char*); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p' : { + width = sizeof(void*) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + const bool is_ll = sizeof(uintptr_t) == sizeof(long long); + if (is_ll) { + idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags); + } + else { +#endif + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%' : + out('%', buffer, idx++, maxlen); + format++; + break; + + default : + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + + +/////////////////////////////////////////////////////////////////////////////// + +int printf_(const char* format, ...) +{ + va_list va; + va_start(va, format); + char buffer[1]; + const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + +int sprintf_(char* buffer, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + +int snprintf_(char* buffer, size_t count, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); + va_end(va); + return ret; +} + + +int vprintf_(const char* format, va_list va) +{ + char buffer[1]; + return _vsnprintf(_out_char, buffer, (size_t)-1, format, va); +} + + +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va) +{ + return _vsnprintf(_out_buffer, buffer, count, format, va); +} + + +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) +{ + va_list va; + va_start(va, format); + const out_fct_wrap_type out_fct_wrap = { out, arg }; + const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va); + va_end(va); + return ret; +} \ No newline at end of file diff --git a/lab8/kernel/src/sdhost.c b/lab8/kernel/src/sdhost.c new file mode 100644 index 000000000..a1faf35cb --- /dev/null +++ b/lab8/kernel/src/sdhost.c @@ -0,0 +1,249 @@ +#include "sdhost.h" + +#include "gpio.h" +#include "printf.h" + +// mmio +// #define KVA 0xffff000000000000 +// #define MMIO_BASE (KVA + 0x3f000000) + +// SD card command +#define GO_IDLE_STATE 0 +#define SEND_OP_CMD 1 +#define ALL_SEND_CID 2 +#define SEND_RELATIVE_ADDR 3 +#define SELECT_CARD 7 +#define SEND_IF_COND 8 +#define VOLTAGE_CHECK_PATTERN 0x1aa +#define STOP_TRANSMISSION 12 +#define SET_BLOCKLEN 16 +#define READ_SINGLE_BLOCK 17 +#define WRITE_SINGLE_BLOCK 24 +#define SD_APP_OP_COND 41 +#define SDCARD_3_3V (1 << 21) +#define SDCARD_ISHCS (1 << 30) +#define SDCARD_READY (1 << 31) +#define APP_CMD 55 + +// gpio +#define GPIO_BASE (MMIO_BASE + 0x200000) +#define GPIO_GPFSEL4 (GPIO_BASE + 0x10) +#define GPIO_GPFSEL5 (GPIO_BASE + 0x14) +#define GPIO_GPPUD (GPIO_BASE + 0x94) +#define GPIO_GPPUDCLK1 (GPIO_BASE + 0x9c) + +// sdhost +#define SDHOST_BASE (MMIO_BASE + 0x202000) +#define SDHOST_CMD (SDHOST_BASE + 0) +#define SDHOST_READ 0x40 +#define SDHOST_WRITE 0x80 +#define SDHOST_LONG_RESPONSE 0x200 +#define SDHOST_NO_REPONSE 0x400 +#define SDHOST_BUSY 0x800 +#define SDHOST_NEW_CMD 0x8000 +#define SDHOST_ARG (SDHOST_BASE + 0x4) +#define SDHOST_TOUT (SDHOST_BASE + 0x8) +#define SDHOST_TOUT_DEFAULT 0xf00000 +#define SDHOST_CDIV (SDHOST_BASE + 0xc) +#define SDHOST_CDIV_MAXDIV 0x7ff +#define SDHOST_CDIV_DEFAULT 0x148 +#define SDHOST_RESP0 (SDHOST_BASE + 0x10) +#define SDHOST_RESP1 (SDHOST_BASE + 0x14) +#define SDHOST_RESP2 (SDHOST_BASE + 0x18) +#define SDHOST_RESP3 (SDHOST_BASE + 0x1c) +#define SDHOST_HSTS (SDHOST_BASE + 0x20) +#define SDHOST_HSTS_MASK (0x7f8) +#define SDHOST_HSTS_ERR_MASK (0xf8) +#define SDHOST_HSTS_DATA (1 << 0) +#define SDHOST_PWR (SDHOST_BASE + 0x30) +#define SDHOST_DBG (SDHOST_BASE + 0x34) +#define SDHOST_DBG_FSM_DATA 1 +#define SDHOST_DBG_FSM_MASK 0xf +#define SDHOST_DBG_MASK (0x1f << 14 | 0x1f << 9) +#define SDHOST_DBG_FIFO (0x4 << 14 | 0x4 << 9) +#define SDHOST_CFG (SDHOST_BASE + 0x38) +#define SDHOST_CFG_DATA_EN (1 << 4) +#define SDHOST_CFG_SLOW (1 << 3) +#define SDHOST_CFG_INTBUS (1 << 1) +#define SDHOST_SIZE (SDHOST_BASE + 0x3c) +#define SDHOST_DATA (SDHOST_BASE + 0x40) +#define SDHOST_CNT (SDHOST_BASE + 0x50) + +// helper +#define set(io_addr, val) \ + asm volatile("str %w1, [%0]" ::"r"(io_addr), "r"(val) : "memory"); + +#define get(io_addr, val) \ + asm volatile("ldr %w0, [%1]" : "=r"(val) : "r"(io_addr) : "memory"); + +static inline void delay(unsigned long tick) { + while (tick--) { + asm volatile("nop"); + } +} + +static int is_hcs; // high capcacity(SDHC) + +static void pin_setup() { + set(GPIO_GPFSEL4, 0x24000000); + set(GPIO_GPFSEL5, 0x924); + set(GPIO_GPPUD, 0); + delay(15000); + + set(GPIO_GPPUDCLK1, 0xffffffff); + delay(15000); + set(GPIO_GPPUDCLK1, 0); +} + +static void sdhost_setup() { + unsigned int tmp; + set(SDHOST_PWR, 0); + set(SDHOST_CMD, 0); + set(SDHOST_ARG, 0); + set(SDHOST_TOUT, SDHOST_TOUT_DEFAULT); + set(SDHOST_CDIV, 0); + set(SDHOST_HSTS, SDHOST_HSTS_MASK); + set(SDHOST_CFG, 0); + set(SDHOST_CNT, 0); + set(SDHOST_SIZE, 0); + get(SDHOST_DBG, tmp); + tmp &= ~SDHOST_DBG_MASK; + tmp |= SDHOST_DBG_FIFO; + set(SDHOST_DBG, tmp); + delay(250000); + set(SDHOST_PWR, 1); + delay(250000); + set(SDHOST_CFG, SDHOST_CFG_SLOW | SDHOST_CFG_INTBUS | SDHOST_CFG_DATA_EN); + set(SDHOST_CDIV, SDHOST_CDIV_DEFAULT); +} + +static int wait_sd() { + int cnt = 1000000; + unsigned int cmd; + do { + if (cnt == 0) { + return -1; + } + get(SDHOST_CMD, cmd); + --cnt; + } while (cmd & SDHOST_NEW_CMD); + return 0; +} + +static int sd_cmd(unsigned cmd, unsigned int arg) { + set(SDHOST_ARG, arg); + set(SDHOST_CMD, cmd | SDHOST_NEW_CMD); + return wait_sd(); +} + +static int sdcard_setup() { + unsigned int tmp; + sd_cmd(GO_IDLE_STATE | SDHOST_NO_REPONSE, 0); + sd_cmd(SEND_IF_COND, VOLTAGE_CHECK_PATTERN); + get(SDHOST_RESP0, tmp); + if (tmp != VOLTAGE_CHECK_PATTERN) { + return -1; + } + while (1) { + if (sd_cmd(APP_CMD, 0) == -1) { + // MMC card or invalid card status + // currently not support + continue; + } + sd_cmd(SD_APP_OP_COND, SDCARD_3_3V | SDCARD_ISHCS); + get(SDHOST_RESP0, tmp); + if (tmp & SDCARD_READY) { + break; + } + delay(1000000); + } + + is_hcs = tmp & SDCARD_ISHCS; + sd_cmd(ALL_SEND_CID | SDHOST_LONG_RESPONSE, 0); + sd_cmd(SEND_RELATIVE_ADDR, 0); + get(SDHOST_RESP0, tmp); + sd_cmd(SELECT_CARD, tmp); + sd_cmd(SET_BLOCKLEN, 512); + return 0; +} + +static int wait_fifo() { + int cnt = 1000000; + unsigned int hsts; + do { + if (cnt == 0) { + return -1; + } + get(SDHOST_HSTS, hsts); + --cnt; + } while ((hsts & SDHOST_HSTS_DATA) == 0); + return 0; +} + +static void set_block(int size, int cnt) { + set(SDHOST_SIZE, size); + set(SDHOST_CNT, cnt); +} + +static void wait_finish() { + unsigned int dbg; + do { + get(SDHOST_DBG, dbg); + } while ((dbg & SDHOST_DBG_FSM_MASK) != SDHOST_HSTS_DATA); +} + +void readblock(int block_idx, void* buf) { + unsigned int* buf_u = (unsigned int*)buf; + int succ = 0; + if (!is_hcs) { + block_idx <<= 9; + } + do { + set_block(512, 1); + sd_cmd(READ_SINGLE_BLOCK | SDHOST_READ, block_idx); + for (int i = 0; i < 128; ++i) { + wait_fifo(); + get(SDHOST_DATA, buf_u[i]); + } + unsigned int hsts; + get(SDHOST_HSTS, hsts); + if (hsts & SDHOST_HSTS_ERR_MASK) { + set(SDHOST_HSTS, SDHOST_HSTS_ERR_MASK); + sd_cmd(STOP_TRANSMISSION | SDHOST_BUSY, 0); + } else { + succ = 1; + } + } while (!succ); + wait_finish(); +} + +void writeblock(int block_idx, void* buf) { + unsigned int* buf_u = (unsigned int*)buf; + int succ = 0; + if (!is_hcs) { + block_idx <<= 9; + } + do { + set_block(512, 1); + sd_cmd(WRITE_SINGLE_BLOCK | SDHOST_WRITE, block_idx); + for (int i = 0; i < 128; ++i) { + wait_fifo(); + set(SDHOST_DATA, buf_u[i]); + } + unsigned int hsts; + get(SDHOST_HSTS, hsts); + if (hsts & SDHOST_HSTS_ERR_MASK) { + set(SDHOST_HSTS, SDHOST_HSTS_ERR_MASK); + sd_cmd(STOP_TRANSMISSION | SDHOST_BUSY, 0); + } else { + succ = 1; + } + } while (!succ); + wait_finish(); +} + +void sd_init() { + pin_setup(); + sdhost_setup(); + sdcard_setup(); +} \ No newline at end of file diff --git a/lab8/kernel/src/shell.c b/lab8/kernel/src/shell.c new file mode 100644 index 000000000..febacfcfd --- /dev/null +++ b/lab8/kernel/src/shell.c @@ -0,0 +1,253 @@ +#include "uart.h" +#include "string.h" +#include "power.h" +#include "mbox.h" +#include "cpio.h" +#include "timer.h" +#include "exception.h" +#include "alloc.h" +#include "utils.h" +#include "thread.h" +#include "printf.h" +#include "dtb.h" +#include "vfs.h" +#include "fatfs.h" + +void clean_buffer(char * buffer, int buffer_len) +{ + for(int i = 0 ; i < buffer_len ; i++) + buffer[i] = '\0'; +} + +void command_help() +{ + uart_puts("This is kernel shell\n"); + uart_puts("help\t\t: print this help menu\n"); + uart_puts("hello\t\t: print Hello World!\n"); + uart_puts("reboot\t\t: reboot the device\n"); + uart_puts("mailbox\t\t: show information through mailbox\n"); + uart_puts("dtb\t\t: parse device tree message\n"); + uart_puts("dtb all\t\t: parse device tree message\n"); + uart_puts("ls\t\t: show all files\n"); + uart_puts("cat\t\t: show file info\n"); + uart_puts("test\t\t: test simple allocator\n"); + uart_puts("user\t\t: load and run a user program in the initramfs\n"); + uart_puts("timer\t\t: core_timer_enable\n"); + uart_puts("puts\t\t: async_puts Test Message\n"); + uart_puts("buddy test\t: test for buddy system\n"); + uart_puts("dma test \t: test for dynamic memory allocation\n"); + uart_puts("setTimeout [MESSAGE] [SECONDS]\t: prints MESSAGE after SECONDS\n"); +} + +void command_hello() +{ + uart_puts("\n"); + uart_puts("Hello World!\n"); +} + +void command_not_found(char * buffer) +{ + uart_puts("\n"); + uart_puts("command *"); + uart_puts(buffer); + uart_puts("* not exist\n"); +} + +void command_ls(){ + cpio_ls(); +} + + +void command_cat(char* pathname){ + cpio_cat(pathname); +} + +void command_mailbox() +{ + // get serail number + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETSERIAL; // get serial number command + mbox[3] = 8; // buffer size + mbox[4] = 8; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + uart_puts("\n"); + if (mbox_call(MBOX_CH_PROP,mbox)) { + uart_puts("serial number is: "); + uart_hex(mbox[6]); + uart_hex(mbox[5]); + uart_puts("\n"); + } + // get board revision + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETBDVS; // get board revision + mbox[3] = 4; // buffer size + mbox[4] = 4; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + if (mbox_call(MBOX_CH_PROP,mbox)) { + uart_puts("board revision is: "); + uart_hex(mbox[6]); + uart_hex(mbox[5]); + uart_puts("\n"); + } + + // get arm memory + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_GETARMMEM; // get arm memory info + mbox[3] = 8; // buffer size + mbox[4] = 8; + mbox[5] = 0; // clear output buffer + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + if (mbox_call(MBOX_CH_PROP,mbox)) { + uart_puts("arm base addr: "); + uart_hex(mbox[5]); + uart_puts("\n"); + uart_puts("arm addr size: "); + uart_hex(mbox[6]); + uart_puts("\n"); + } +} + +void command_test() +{ + // test malloc + uart_puts("\r"); + uart_puts("test malloc\n"); + char * c = malloc(30); + c[0]='a'; + c[1]='b'; + c[2]='\0'; + uart_puts("c:"); + uart_puts(c); + uart_puts("\r\n"); + char * d = malloc(30); + d[0]='x'; + d[1]='y'; + d[2]='\0'; + uart_puts("d:"); + uart_puts(d); + uart_puts("\r\n"); +} + +void command_load_user_program(const char *program_name) { + uint64_t spsr_el1 = 0x0; // EL0t with interrupt enabled + uint64_t target_addr = 0x30100000; + uint64_t target_sp = 0x10007030; + cpio_load_user_program(program_name, target_addr); + // core_timer_enable(); + asm volatile("msr spsr_el1, %0" : : "r"(spsr_el1)); + asm volatile("msr elr_el1, %0" : : "r"(target_addr)); + asm volatile("msr sp_el0, %0" : : "r"(target_sp)); + asm volatile("eret"); +} + +void command_set_timeout(char *args) { + uint32_t duration = 0; + for (int i = 0; args[i]; i++) { + if (args[i] == ' ') { + for (int j = i + 1; args[j]; j++) { + duration = duration * 10 + (args[j] - '0'); + } + args[i] = '\0'; + break; + } + } + add_timer(timer_callback, args, duration); +} + +void command_buddy_test() { + buddy_test(); +} +void command_dma_test() { + dma_test(); +} +void command_thread_test1() { + thread_test1(); +} +void command_thread_test2() { + thread_test2(); +} +void command_thread_test3() { + thread_test3(); +} +void command_thread_test4() { + thread_test4(); +} + +void commandd_vfs_test() { vfs_test(); } + + +void command_dtb_print(int all) { dtb_print(all); } + +void parse_command(char * buffer) +{ + if ( !strcmp(buffer, "help")) command_help(); + else if ( !strcmp(buffer, "hello")) command_hello(); + else if ( !strcmp(buffer, "mailbox")) command_mailbox(); + else if ( !strcmp(buffer, "ls")) command_ls(); + else if ( !strncmp(buffer, "cat", 3)) command_cat(&buffer[4]); + else if ( !strcmp(buffer, "test")) command_test(); + else if ( !strcmp(buffer, "reboot")) reset(); + else if ( !strncmp(buffer, "run", 3)) command_load_user_program(&buffer[4]); + else if ( !strcmp(buffer, "puts")) uart_async_puts("Test Message!\n"); + else if ( !strcmp(buffer, "timer")) core_timer_enable(); + else if ( !strncmp(buffer, "setTimeout", 10)) command_set_timeout(&buffer[11]); + else if ( !strcmp(buffer, "buddy test")) command_buddy_test(); + else if ( !strcmp(buffer, "dma test")) command_dma_test(); + else if ( !strcmp(buffer, "dtb")) command_dtb_print(0); + else if ( !strcmp(buffer, "dtb all")) command_dtb_print(1); + else if ( !strcmp(buffer, "t1")) command_thread_test1(); + else if ( !strcmp(buffer, "t2")) command_thread_test2(); + else if ( !strcmp(buffer, "t3")) command_thread_test3(); + else if ( !strcmp(buffer, "t4")) command_thread_test4(); + else if ( !strcmp(buffer, "vfs")) vfs_test(); + else if ( !strcmp(buffer, "list_sd")) list_sd(); + else command_not_found(buffer); +} + +void run_shell() +{ + char buffer[64]={'\0'}; + int buffer_len=0; + //clean buffer + clean_buffer(buffer, 64); + // echo everything back + while(1) { + printf("# "); + while(1){ + char c = uart_async_getc(); + if(c=='\n')uart_send('\r'); + uart_send(c); + if(c=='\n'){ + //parse buffer + parse_command(buffer); + //clean buffer + clean_buffer(buffer, 64); + buffer_len = 0; + break; + } + //backspace + if (c == 127) { + if (buffer_len > 0) { + printf("\b \b"); + buffer[--buffer_len] = '\0'; + } + continue; + } + buffer[buffer_len++] = c; + } + } +} diff --git a/lab8/kernel/src/start.S b/lab8/kernel/src/start.S new file mode 100644 index 000000000..ccc0e40fb --- /dev/null +++ b/lab8/kernel/src/start.S @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +.section ".text.boot" + +.global _start + +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #3 + cbz x1, master + b hang_loop // cpu id > 0, stop + +master: // cpu id == 0 + + // save dtb loading address + ldr x1, =0x9000000 + str x0, [x1] + + bl from_el2_to_el1 + bl set_exception_vector_table + + // clear bss + ldr x1, =__bss_start + ldr w2, =__bss_size + +clear_bss_start: + cbz w2, clear_bss_done + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, clear_bss_start + + +clear_bss_done: + // set top of stack just before our code (stack grows to a lower address per AAPCS64) + ldr x1, =_start + mov sp, x1 + + bl main // jump to C code, should not return + b hang_loop // for failsafe, halt this core too + +from_el2_to_el1: + mov x0, (1 << 31) // EL1 uses aarch64 + msr hcr_el2, x0 + mov x0, 0x3c5 // EL1h with interrupt disabled + msr spsr_el2, x0 + msr elr_el2, lr + + // IMPORTANT: disable exceptions of accessing the SIMD and floating-point registers + mov x0, #(3 << 20) + msr cpacr_el1, x0 + + eret // return to EL1 + +set_exception_vector_table: + adr x0, exception_vector_table + msr vbar_el1, x0 + ret + +hang_loop: + wfe + b hang_loop \ No newline at end of file diff --git a/lab8/kernel/src/string.c b/lab8/kernel/src/string.c new file mode 100644 index 000000000..aa38ba5bf --- /dev/null +++ b/lab8/kernel/src/string.c @@ -0,0 +1,165 @@ +#include "string.h" + +/* Compare S1 and S2, returning less than, equal to or + greater than zero if S1 is lexicographically less than, + equal to or greater than S2. */ +int strcmp(const char *p1, const char *p2) { + const unsigned char *s1 = (const unsigned char *)p1; + const unsigned char *s2 = (const unsigned char *)p2; + unsigned char c1, c2; + do { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0') return c1 - c2; + } while (c1 == c2); + return c1 - c2; +} + +/* Compare no more than N characters of S1 and S2, + returning less than, equal to or greater than zero + if S1 is lexicographically less than, equal to or + greater than S2. */ +int strncmp(const char *s1, const char *s2, unsigned n) { + unsigned char c1 = '\0'; + unsigned char c2 = '\0'; + if (n >= 4) { + unsigned n4 = n >> 2; + do { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + } while (--n4 > 0); + n &= 3; + } + while (n > 0) { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) return c1 - c2; + n--; + } + return c1 - c2; +} + +int strlen(const char *s) { + int len = 0; + while (s[len] != '\0') { + len++; + } + return len; +} + +/* + * Find the first occurrence of find in s. + */ +char *strstr(const char *s, const char *find) { + char c, sc; + int len; + if ((c = *find++) != 0) { + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) return 0; + } while (sc != c); + } while (strncmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} + +char *strcpy(char *dst, const char *src) { + // return if no memory is allocated to the destination + if (dst == 0) return 0; + + char *ptr = dst; + while (*src != '\0') { + *dst = *src; + dst++; + src++; + } + *dst = '\0'; + return ptr; +} + +char *strncpy(char *dst, const char *src, size_t len) { + // return if no memory is allocated to the destination + if (dst == 0) return 0; + + // take a pointer pointing to the beginning of destination string + char *ptr = dst; + + // copy the C-string pointed by source into the array + // pointed by destination + while (*src != ' ') { + *dst = *src; + dst++; + src++; + len--; + if (!len) { + break; + } + } + + // include the terminating null character + *dst = '\0'; + + // destination is returned by standard strcpy() + return ptr; +} + +void strcat(char *to, const char *from) { + while (*to) { + to++; + } + while (*from) { + *to = *from; + to++; + from++; + } + *to = '\0'; +} + +char *strtok(char *s, const char delim) { + static char *pos; + char *ret; + if (s) pos = s; + + if (*pos == '\0') return 0; + // skip leading + while (*pos == delim) { + pos++; + } + + ret = pos; + while (*pos != delim && *pos != '\0') { + pos++; + } + if (*pos != '\0') { + *pos = '\0'; + pos++; + } + return ret; +} + +char *split_last(char *str, char delim) { + char *mid = 0; + while (*str) { + if (*str == delim) { + mid = str; + } + str++; + } + if (mid) { + *mid = '\0'; + mid++; + } + return mid; +} \ No newline at end of file diff --git a/lab8/kernel/src/thread.S b/lab8/kernel/src/thread.S new file mode 100644 index 000000000..514958efa --- /dev/null +++ b/lab8/kernel/src/thread.S @@ -0,0 +1,26 @@ +.global switch_to +switch_to: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + + ldp x19, x20, [x1, 16 * 0] + ldp x21, x22, [x1, 16 * 1] + ldp x23, x24, [x1, 16 * 2] + ldp x25, x26, [x1, 16 * 3] + ldp x27, x28, [x1, 16 * 4] + ldp fp, lr, [x1, 16 * 5] + ldr x9, [x1, 16 * 6] + mov sp, x9 + msr tpidr_el1, x1 + ret + +.global get_current +get_current: + mrs x0, tpidr_el1 + ret \ No newline at end of file diff --git a/lab8/kernel/src/thread.c b/lab8/kernel/src/thread.c new file mode 100644 index 000000000..b7c4dc65b --- /dev/null +++ b/lab8/kernel/src/thread.c @@ -0,0 +1,305 @@ +#include "thread.h" +#include "timer.h" +#include "alloc.h" +#include "cpio.h" +#include "exception.h" +#include "printf.h" +#include "utils.h" +#include "shell.h" + +void foo() { + for (int i = 0; i < 4; ++i) { + printf("Thread id: %d, %d\r\n", get_current()->pid, i); + delay(1000000); + schedule(); + } + exit(); + return; +} + +void user_test1() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("my_test", argv); +} + +void user_test2() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("my_test2", argv); +} +void user_test3() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("fork_test", argv); +} + +void user_test4() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("vfs1.img", argv); +} + +void user_test5() { + const char *argv[] = {"argv_test", "-o", "arg2", 0}; + exec("vfs2.img", argv); +} + +void thread_test1() { // thread test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test1); + thread_create(user_test2); + idle(); +} + +void thread_test2() { // fork test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test3); + idle(); +} + +void thread_test3() { //vedio player1 test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test4); + idle(); +} + +void thread_test4() { //vedio player1 test + thread_info *idle_t = thread_create(0); + asm volatile("msr tpidr_el1, %0\n" ::"r"((uint64_t)idle_t)); + thread_create(user_test5); + idle(); +} + +void thread_init() { + run_queue.head = 0; + run_queue.tail = 0; + thread_cnt = 0; + + stdin = vfs_open("/dev/uart", 0); + stdout = vfs_open("/dev/uart", 0); + stderr = vfs_open("/dev/uart", 0); +} + +thread_info *thread_create(void (*func)()) { + // printf("create thread pid = %d\n",thread_cnt); + thread_info *thread = (thread_info *)malloc(sizeof(thread_info)); + thread->pid = thread_cnt++; + thread->status = THREAD_READY; + thread->next = 0; + thread->kernel_stack_base = (uint64_t)malloc(STACK_SIZE); + thread->user_stack_base = (uint64_t)malloc(STACK_SIZE); + thread->user_program_base = + USER_PROGRAM_BASE + thread->pid * USER_PROGRAM_SIZE; + thread->context.fp = thread->kernel_stack_base + STACK_SIZE; + thread->context.lr = (uint64_t)func; + thread->context.sp = thread->kernel_stack_base + STACK_SIZE; + for (int i = 0; i < FD_MAX; ++i) thread->fd_table.files[i] = 0; + thread->fd_table.files[0] = stdin; + thread->fd_table.files[1] = stdout; + thread->fd_table.files[2] = stderr; + run_queue_push(thread); + return thread; +} + +void schedule() { + // printf("[schdule]\n"); + if (run_queue.head == 0) { + // printf("no thread\n"); + enable_uart_interrupt(); + core_timer_disable(); + enable_interrupt(); + return; + } + if (run_queue.head == run_queue.tail) { // idle thread + // printf("left idle thread\n"); + free(run_queue.head); + run_queue.head = run_queue.tail = 0; + thread_cnt = 0; + enable_interrupt(); // need uart interrupt when go back to shell + return; + } + + do { + run_queue.tail->next = run_queue.head; + run_queue.tail = run_queue.head; + run_queue.head = run_queue.head->next; + run_queue.tail->next = 0; + } while (run_queue.head->status != THREAD_READY); + // printf("get_current()->pid = %d\n",get_current()->pid); + // printf("run_queue.head->pid = %d\n",run_queue.head->pid); + enable_interrupt(); + switch_to(get_current(), run_queue.head); +} + +void idle() { + // printf("[idle]\n"); + + while (1) { + kill_zombies(); + handle_fork(); + schedule(); + if (run_queue.head == 0) break; //blcok here if any thread exist= + } +} + +void exit() { + thread_info *cur = get_current(); + cur->status = THREAD_DEAD; + schedule(); +} + +void run_queue_push(thread_info *thread) { + if (run_queue.head == 0) { + run_queue.head = run_queue.tail = thread; + } else { + run_queue.tail->next = thread; + run_queue.tail = thread; + } +} + +void kill_zombies() { + if (run_queue.head == 0) return; + for (thread_info *ptr = run_queue.head; ptr->next != 0; ptr = ptr->next) { + for (thread_info *cur = ptr->next; + cur != 0 && (cur->status == THREAD_DEAD);) { + thread_info *tmp = cur->next; + free((void *)cur); + ptr->next = tmp; + cur = tmp; + } + if (ptr->next == 0) { + run_queue.tail = ptr; + break; + } + } +} + +void exec(const char *program_name, const char **argv) { + thread_info *cur = get_current(); + + uint64_t user_sp = cur->user_stack_base + STACK_SIZE; + cur->user_program_size = cpio_load_user_program(program_name, cur->user_program_base); + // printf("cur->pid = %d, cur->user_program_base = %x\n",cur->pid,cur->user_program_base); + + // return to user program + uint64_t spsr_el1 = 0x0; // EL0t with interrupt enabled + uint64_t target_addr = cur->user_program_base; + uint64_t target_sp = user_sp; + core_timer_enable(); + asm volatile("msr spsr_el1, %0" : : "r"(spsr_el1)); + asm volatile("msr elr_el1, %0" : : "r"(target_addr)); + asm volatile("msr sp_el0, %0" : : "r"(target_sp)); + asm volatile("eret"); +} + +void fork(uint64_t sp) { + run_queue.head->status = THREAD_FORK; + run_queue.head->trap_frame_addr = sp; + schedule(); + trap_frame_t *trap_frame = (trap_frame_t *)(get_current()->trap_frame_addr); + trap_frame->x[0] = run_queue.head->child_pid; +} + +void handle_fork() { + // printf("[handle_fork]\n"); + for (thread_info *ptr = run_queue.head->next; ptr != 0; ptr = ptr->next) { + if ((ptr->status) == THREAD_FORK) { + thread_info *child = thread_create(0); + create_child(ptr, child); + ptr->status = THREAD_READY; + child->status = THREAD_READY; + } + } +} + +void create_child(thread_info *parent, thread_info *child) { + // printf("[create_child]\n"); + disable_interrupt(); + child->user_stack_base = (uint64_t)malloc(STACK_SIZE); + child->user_program_size = parent->user_program_size; + parent->child_pid = child->pid; + child->child_pid = 0; + + char *src, *dst; + // copy saved context in thread info + src = (char *)&(parent->context); + dst = (char *)&(child->context); + for (uint32_t i = 0; i < sizeof(cpu_context); ++i, ++src, ++dst) { + *dst = *src; + } + // copy kernel stack + src = (char *)(parent->kernel_stack_base); + dst = (char *)(child->kernel_stack_base); + for (uint32_t i = 0; i < STACK_SIZE; ++i, ++src, ++dst) { + *dst = *src; + } + // copy user stack + src = (char *)(parent->user_stack_base); + dst = (char *)(child->user_stack_base); + for (uint32_t i = 0; i < STACK_SIZE; ++i, ++src, ++dst) { + *dst = *src; + } + // copy user program + src = (char *)(parent->user_program_base); + dst = (char *)(child->user_program_base); + for (uint32_t i = 0; i < parent->user_program_size; ++i, ++src, ++dst) { + *dst = *src; + } + + // set correct address for child + uint64_t kernel_stack_base_dist = + child->kernel_stack_base - parent->kernel_stack_base; + uint64_t user_stack_base_dist = + child->user_stack_base - parent->user_stack_base; + uint64_t user_program_base_dist = + child->user_program_base - parent->user_program_base; + + child->context.fp += kernel_stack_base_dist; + child->context.sp += kernel_stack_base_dist; + child->trap_frame_addr = parent->trap_frame_addr + kernel_stack_base_dist; + trap_frame_t *trap_frame = (trap_frame_t *)(child->trap_frame_addr); + trap_frame->x[29] += user_stack_base_dist; // fp (x29) + trap_frame->x[30] += user_program_base_dist; // lr (x30) + trap_frame->x[32] += user_program_base_dist; // elr_el1 + trap_frame->x[33] += user_stack_base_dist; // sp_el0 + enable_interrupt(); +} +void kill (int kill_pid) +{ + if (run_queue.head == 0) return; + for (thread_info *ptr = run_queue.head; ptr->next != 0; ptr = ptr->next) { + if(ptr->pid == kill_pid){ + printf("Kill pid = %d\n",kill_pid); + ptr->status = THREAD_DEAD; + schedule(); + return; + } + } + printf("pid = %d not exist\n",kill_pid); + +} + +struct file *thread_get_file(int fd) { + thread_info *cur = get_current(); + return cur->fd_table.files[fd]; +} + +int thread_register_fd(struct file *file) { + if (file == 0) return -1; + thread_info *cur = get_current(); + // find next available fd + for (int fd = 3; fd < FD_MAX; ++fd) { + if (cur->fd_table.files[fd] == 0) { + cur->fd_table.files[fd] = file; + return fd; + } + } + return -1; +} + +int thread_clear_fd(int fd) { + if (fd < 0 || fd >= FD_MAX) return -1; + thread_info *cur = get_current(); + cur->fd_table.files[fd] = 0; + return 1; +} \ No newline at end of file diff --git a/lab8/kernel/src/timer.c b/lab8/kernel/src/timer.c new file mode 100644 index 000000000..02095c58d --- /dev/null +++ b/lab8/kernel/src/timer.c @@ -0,0 +1,146 @@ +#include "timer.h" +#include "alloc.h" +#include "uart.h" +#include "utils.h" +#include "thread.h" + +void timeout_event_init() { + timeout_queue_head = 0; + timeout_queue_tail = 0; +} + +void core_timer_enable() { + asm volatile("mov x0, 1"); + asm volatile("msr cntp_ctl_el0, x0"); // enable + asm volatile("mrs x0, cntfrq_el0"); + asm volatile("msr cntp_tval_el0, x0"); // set expired time + asm volatile("mov x0, 2"); + asm volatile("ldr x1, =0x40000040"); + asm volatile("str w0, [x1]"); // unmask timer interrupt + + uint64_t tmp; + asm volatile("mrs %0, cntkctl_el1" : "=r"(tmp)); + tmp |= 1; + asm volatile("msr cntkctl_el1, %0" : : "r"(tmp)); +} + +// void core_timer_handler() { +// uart_puts("===== timer handler =====\n"); +// uint64_t cntpct_el0, cntfrq_el0; +// asm volatile("mrs %0, cntpct_el0" : "=r"(cntpct_el0)); +// asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq_el0)); +// asm volatile("mrs x0, cntfrq_el0"); +// asm volatile("mov x1, 2"); +// asm volatile("mul x0, x0, x1"); +// asm volatile("msr cntp_tval_el0, x0"); +// uart_puts("Time elapsed after booting: "); +// // char c = cntpct_el0 / cntfrq_el0; +// uart_int(cntpct_el0 / cntfrq_el0); +// uart_puts("s\n"); +// } + +void core_timer_disable() { + asm volatile("mov x0, 0"); + asm volatile("msr cntp_ctl_el0, x0"); // disable + asm volatile("mov x0, 0"); + asm volatile("ldr x1, =0x40000040"); + asm volatile("str w0, [x1]"); // unmask timer interrupt +} + +void core_timer_handler_lowerEL_64() { // required 2 + set_expired_time(1); + // uart_puts("Time elapsed after booting: "); + // uart_int(get_current_time()); + // uart_puts("s\n"); + schedule(); +} + +void core_timer_handler_currentEL_ELx() { // elective 2 + uart_puts("Current time: "); + uart_int(get_current_time()); + uart_puts("s, "); + uart_puts("Command executed time: "); + uart_int(timeout_queue_head->register_time); + uart_puts("s, "); + uart_puts("Duration: "); + uart_int(timeout_queue_head->duration); + uart_puts("s\n"); + timeout_queue_head->callback(timeout_queue_head->args); + timeout_event *next = timeout_queue_head->next; + // free(timeout_queue_head); + if (next) { + next->prev = 0; + timeout_queue_head = next; + uint64_t next_duration = + next->register_time + next->duration - get_current_time(); + set_expired_time(next_duration); + } else { + timeout_queue_head = 0; + timeout_queue_tail = 0; + core_timer_disable(); + } +} + +void add_timer(void (*callback)(char *), char *args, uint32_t duration) { + timeout_event *new_timeout_event = + (timeout_event *)malloc(sizeof(timeout_event)); + new_timeout_event->register_time = get_current_time(); + new_timeout_event->duration = duration; + new_timeout_event->callback = callback; + for (int i = 0; i < 20; i++) { + new_timeout_event->args[i] = args[i]; + if (args[i] == '\0') break; + } + new_timeout_event->prev = 0; + new_timeout_event->next = 0; + + if (timeout_queue_head == 0) { + timeout_queue_head = new_timeout_event; + timeout_queue_tail = new_timeout_event; + core_timer_enable(); + set_expired_time(duration); + } else { + timeout_event *cur; + uint64_t timeout = + new_timeout_event->register_time + new_timeout_event->duration; + for (cur = timeout_queue_head; cur; cur = cur->next) { + if (cur->register_time + cur->duration > timeout) break; + } + + if (cur == 0) { + new_timeout_event->prev = timeout_queue_tail; + timeout_queue_tail->next = new_timeout_event; + timeout_queue_tail = new_timeout_event; + } else if (cur->prev == 0) { + new_timeout_event->next = cur; + timeout_queue_head->prev = new_timeout_event; + timeout_queue_head = new_timeout_event; + set_expired_time(duration); + } else { + new_timeout_event->prev = cur->prev; + new_timeout_event->next = cur; + cur->prev->next = new_timeout_event; + cur->prev = new_timeout_event; + } + } +} + +uint64_t get_current_time() { + uint64_t cntpct_el0, cntfrq_el0; + asm volatile("mrs %0, cntpct_el0" : "=r"(cntpct_el0)); + asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq_el0)); + return cntpct_el0 / cntfrq_el0; +} + + +void set_expired_time(uint32_t duration) { + uint64_t cntfrq_el0; + asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq_el0)); + asm volatile("msr cntp_tval_el0, %0" : : "r"(cntfrq_el0 * duration / 32)); +} + +void timer_callback(char *msg) { + uart_puts("Message: "); + uart_puts(msg); + uart_puts("\n"); +} \ No newline at end of file diff --git a/lab8/kernel/src/tmpfs.c b/lab8/kernel/src/tmpfs.c new file mode 100644 index 000000000..4a066b445 --- /dev/null +++ b/lab8/kernel/src/tmpfs.c @@ -0,0 +1,142 @@ +#include "tmpfs.h" + +#include "alloc.h" +#include "printf.h" +#include "string.h" +#include "vfs.h" + +void tmpfs_init() { + tmpfs_v_ops = + (struct vnode_operations*)malloc(sizeof(struct vnode_operations)); + tmpfs_v_ops->lookup = tmpfs_lookup; + tmpfs_v_ops->create = tmpfs_create; + tmpfs_v_ops->set_parent = tmpfs_set_parent; + tmpfs_f_ops = (struct file_operations*)malloc(sizeof(struct file_operations)); + tmpfs_f_ops->write = tmpfs_write; + tmpfs_f_ops->read = tmpfs_read; + tmpfs_f_ops->list = tmpfs_list; +} + +void tmpfs_set_fentry(struct tmpfs_fentry* fentry, const char* component_name, + FILE_TYPE type, struct vnode* vnode) { + strcpy(fentry->name, component_name); + fentry->vnode = vnode; + fentry->type = type; + fentry->buf = (struct tmpfs_buf*)malloc(sizeof(struct tmpfs_buf)); + for (int i = 0; i < TMPFS_BUF_SIZE; i++) { + fentry->buf->buffer[i] = '\0'; + } + + if (fentry->type == FILE_DIRECTORY) { + for (int i = 0; i < MAX_FILES_IN_DIR; ++i) { + fentry->child[i] = + (struct tmpfs_fentry*)malloc(sizeof(struct tmpfs_fentry)); + fentry->child[i]->name[0] = 0; + fentry->child[i]->type = FILE_NONE; + fentry->child[i]->parent_vnode = vnode; + } + fentry->buf->size = TMPFS_BUF_SIZE; + } else if (fentry->type == FILE_REGULAR) { + fentry->buf->size = 0; + } +} + +int tmpfs_setup_mount(struct filesystem* fs, struct mount* mount) { + struct tmpfs_fentry* root_fentry = + (struct tmpfs_fentry*)malloc(sizeof(struct tmpfs_fentry)); + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = mount; + vnode->v_ops = tmpfs_v_ops; + vnode->f_ops = tmpfs_f_ops; + vnode->internal = (void*)root_fentry; + root_fentry->parent_vnode = 0; + tmpfs_set_fentry(root_fentry, "/", FILE_DIRECTORY, vnode); + mount->fs = fs; + mount->root = vnode; + return 1; +} + +int tmpfs_lookup(struct vnode* dir_node, struct vnode** target, + const char* component_name) { + // printf("[lookup] %s\n", component_name); + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)dir_node->internal; + if (fentry->type != FILE_DIRECTORY) return 0; + + if (!strcmp(component_name, ".")) { + *target = fentry->vnode; + return 1; + } + if (!strcmp(component_name, "..")) { + if (!fentry->parent_vnode) return 0; + *target = fentry->parent_vnode; + return 1; + } + + for (int i = 0; i < MAX_FILES_IN_DIR; i++) { + fentry = ((struct tmpfs_fentry*)dir_node->internal)->child[i]; + if (!strcmp(fentry->name, component_name)) { + *target = fentry->vnode; + return 1; + } + } + return 0; +} + +int tmpfs_create(struct vnode* dir_node, struct vnode** target, + const char* component_name, FILE_TYPE type) { + for (int i = 0; i < MAX_FILES_IN_DIR; i++) { + struct tmpfs_fentry* fentry = + ((struct tmpfs_fentry*)dir_node->internal)->child[i]; + if (fentry->type == FILE_NONE) { + struct vnode* vnode = (struct vnode*)malloc(sizeof(struct vnode)); + vnode->mount = 0; + vnode->v_ops = dir_node->v_ops; + vnode->f_ops = dir_node->f_ops; + vnode->internal = fentry; + tmpfs_set_fentry(fentry, component_name, type, vnode); + *target = fentry->vnode; + return 1; + } + } + return -1; +} + +int tmpfs_set_parent(struct vnode* child_node, struct vnode* parent_vnode) { + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)child_node->internal; + fentry->parent_vnode = parent_vnode; + return 1; +} + +int tmpfs_write(struct file* file, const void* buf, size_t len) { + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)file->vnode->internal; + for (size_t i = 0; i < len; i++) { + fentry->buf->buffer[file->f_pos++] = ((char*)buf)[i]; + if (fentry->buf->size < file->f_pos) { + fentry->buf->size = file->f_pos; + } + } + return len; +} + +int tmpfs_read(struct file* file, void* buf, size_t len) { + size_t read_len = 0; + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)file->vnode->internal; + for (size_t i = 0; i < len; i++) { + ((char*)buf)[i] = fentry->buf->buffer[file->f_pos++]; + read_len++; + if (read_len == fentry->buf->size) { + break; + } + } + return read_len; +} + +int tmpfs_list(struct file* file, void* buf, int index) { + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)file->vnode->internal; + if (fentry->type != FILE_DIRECTORY) return -1; + if (index >= MAX_FILES_IN_DIR) return -1; + + if (fentry->child[index]->type == FILE_NONE) return 0; + strcpy((char*)buf, fentry->child[index]->name); + return fentry->child[index]->buf->size; +} \ No newline at end of file diff --git a/lab8/kernel/src/uart.c b/lab8/kernel/src/uart.c new file mode 100644 index 000000000..44d542e1f --- /dev/null +++ b/lab8/kernel/src/uart.c @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "gpio.h" +#include "utils.h" +#include "uart.h" +#include "vfs.h" + +/* Auxilary mini UART registers */ +#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004)) +#define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE+0x00215040)) +#define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE+0x00215044)) +#define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE+0x00215048)) +#define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE+0x0021504C)) +#define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE+0x00215050)) +#define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE+0x00215054)) +#define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE+0x00215058)) +#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE+0x0021505C)) +#define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE+0x00215060)) +#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064)) +#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068)) +/** + * Set baud rate and characteristics (115200 8N1) and map to GPIO + */ +void uart_init() +{ + register unsigned int r; + + /* initialize UART */ + *AUX_ENABLE |=1; // enable UART1, AUX mini uart + *AUX_MU_CNTL = 0; + *AUX_MU_LCR = 3; // 8 bits + *AUX_MU_MCR = 0; + *AUX_MU_IER = 1; + // comment this line to avoid weird character + // *AUX_MU_IIR = 0xc6; // disable interrupts + *AUX_MU_BAUD = 270; // 115200 baud + /* map UART1 to GPIO pins */ + r=*GPFSEL1; + r&=~((7<<12)|(7<<15)); // gpio14, gpio15 + r|=(2<<12)|(2<<15); // alt5 + *GPFSEL1 = r; + *GPPUD = 0; // enable pins 14 and 15 + r=150; while(r--) { asm volatile("nop"); } + *GPPUDCLK0 = (1<<14)|(1<<15); + r=150; while(r--) { asm volatile("nop"); } + *GPPUDCLK0 = 0; // flush GPIO setup + *AUX_MU_CNTL = 3; // enable Tx, Rx + + read_buf_start = read_buf_end = 0; + write_buf_start = write_buf_end = 0; + enable_uart_interrupt(); +} + +/** + * Send a character + */ +void uart_send(unsigned int c) { + /* wait until we can send */ + do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x20)); + /* write the character to the buffer */ + *AUX_MU_IO=c; +} + +/** + * Receive a character + */ +char uart_getc() { + char r; + /* wait until something is in the buffer */ + do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01)); + /* read it and return */ + r=(char)(*AUX_MU_IO); + /* convert carrige return to newline */ + return r=='\r'?'\n':r; +} + +uint32_t uart_gets(char *buf, uint32_t size) { + for (int i = 0; i < size; ++i) { + buf[i] = uart_getc(); + // uart_send(buf[i]); + if (buf[i] == '\n' || buf[i] == '\r') { + // uart_send('\r'); + // buf[i] = '\0'; + return i; + } + } + return size; +} + +/** + * Display a string + */ +void uart_puts(char *s) { + while(*s) { + /* convert newline to carrige return + newline */ + if(*s=='\n') + uart_send('\r'); + uart_send(*s++); + } +} + +uint32_t uart_write(char *s, uint32_t size) { + for(int i = 0 ; i=0;c-=4) { + // get highest tetrad + n=(d>>c)&0xF; + // 0-9 => '0'-'9', 10-15 => 'A'-'F' + n+=n>9?0x37:0x30; + uart_send(n); + } +} + +void uart_int(int x) { + if (x < 0) { + uart_send('-'); + x = -x; + } + if (x >= 10) uart_int(x / 10); + uart_send(x % 10 + '0'); +} + +void enable_uart_interrupt() { *ENABLE_IRQS_1 = AUX_IRQ; } + +void disable_uart_interrupt() { *DISABLE_IRQS_1 = AUX_IRQ; } + +void assert_transmit_interrupt() { *AUX_MU_IER |= 0x2; } + +void clear_transmit_interrupt() { *AUX_MU_IER &= ~(0x2); } + +void uart_handler() { + disable_uart_interrupt(); + int is_read = (*AUX_MU_IIR & 0x4); + int is_write = (*AUX_MU_IIR & 0x2); + + if (is_read) { + // uart_puts("===== is_read =====\n"); + + char c = (char)(*AUX_MU_IO); + read_buf[read_buf_end++] = c; + if (read_buf_end == UART_BUFFER_SIZE) read_buf_end = 0; + } else if (is_write) { + // uart_puts("===== is_write =====\n"); + + while (*AUX_MU_LSR & 0x20) { + if (write_buf_start == write_buf_end) { + clear_transmit_interrupt(); + break; + } + char c = write_buf[write_buf_start++]; + *AUX_MU_IO = c; + if (write_buf_start == UART_BUFFER_SIZE) write_buf_start = 0; + } + } + enable_uart_interrupt(); +} + +char uart_async_getc() { + // wait until there are new data + // uart_puts("===== uart getc =====\n"); + while (read_buf_start == read_buf_end) { + // uart_puts("===== read_buf_start == read_buf_end =====\n"); + asm volatile("nop"); + } + char c = read_buf[read_buf_start++]; + if (read_buf_start == UART_BUFFER_SIZE) read_buf_start = 0; + // '\r' => '\n' + return c == '\r' ? '\n' : c; +} + +void uart_async_puts(char *str) { + for (int i = 0; str[i]; i++) { + if (str[i] == '\n') write_buf[write_buf_end++] = '\r'; + write_buf[write_buf_end++] = str[i]; + if (write_buf_end == UART_BUFFER_SIZE) write_buf_end = 0; + } + assert_transmit_interrupt(); +} diff --git a/lab8/kernel/src/utils.S b/lab8/kernel/src/utils.S new file mode 100644 index 000000000..894a1fdc8 --- /dev/null +++ b/lab8/kernel/src/utils.S @@ -0,0 +1,9 @@ +.globl put32 +put32: + str w1, [x0] + ret + +.globl get32 +get32: + ldr w0, [x0] + ret diff --git a/lab8/kernel/src/utils.c b/lab8/kernel/src/utils.c new file mode 100644 index 000000000..8047ee2c7 --- /dev/null +++ b/lab8/kernel/src/utils.c @@ -0,0 +1,71 @@ +// typedef unsigned long long int uint64_t; +// typedef unsigned char uint8_t; +#include "utils.h" + +uint8_t hex_to_int8(char hex){ + if(hex >= '0' && hex <= '9') + return hex-'0'; + else if(hex >= 'A' && hex <= 'Z') + return hex-'A'+10; + else if(hex >= 'a' && hex <= 'z') + return hex-'a'+10; + else + return -1; +} + +uint64_t hex_to_int64(char* num){ + uint64_t res=0; + for(int i=0; i<8; i++){ + res = (res<<4) + hex_to_int8(num[i]); + } + return res; +} + +uint64_t log2(uint64_t num) { + for (uint64_t i = 0; i < 64; i++) { + if (num == (1 << i)) return i; + } + return 0; +} +uint64_t align_up(uint64_t addr, uint64_t alignment) { + return (addr + alignment - 1) & (~(alignment - 1)); +} + +uint64_t align_up_exp(uint64_t n) { + n--; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n |= n >> 32; + n++; + return n; +} + +void delay(int num) { + while (num--) + ; +} + +uint64_t hex2int(char *hex, int len) { + uint64_t val = 0; + for (int i = 0; i < len; i++) { + // get current character then increment + uint64_t byte = *(hex + i); + if (byte >= '0' && byte <= '9') + byte = byte - '0'; + else if (byte >= 'A' && byte <= 'F') + byte = byte - 'A' + 10; + else if (byte >= 'a' && byte <= 'f') + byte = byte - 'a' + 10; + + val = (val << 4) | (byte & 0xF); + } + return val; +} + +uint32_t be2le(uint32_t x) { + return (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) | + (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); +} \ No newline at end of file diff --git a/lab8/kernel/src/vfs.c b/lab8/kernel/src/vfs.c new file mode 100644 index 000000000..f18ada3fa --- /dev/null +++ b/lab8/kernel/src/vfs.c @@ -0,0 +1,352 @@ +#include "vfs.h" + +#include "alloc.h" +#include "cpio.h" +#include "fatfs.h" +#include "printf.h" +#include "string.h" +#include "thread.h" +#include "tmpfs.h" +#include "device.h" + +void vfs_test() { + const char* argv[] = {"vfs_test", 0}; + exec("vfs_test", argv); +} + +void vfs_ls_test() { + const char* argv[] = {"ls", ".", 0}; + exec("ls", argv); +} + +void vfs_hard_test() { + const char* argv[] = {"vfs_test_hard", 0}; + exec("vfs_test_hard", argv); +} + +void vfs_fat_test() { + const char* argv[] = {"fatfs_test", 0}; + exec("fatfs_test", argv); +} + +void vnode_print( struct vnode* vnode){ + struct tmpfs_fentry* fentry = (struct tmpfs_fentry*) vnode->internal; + printf("[vnode_print]name = %s\n", fentry->name); +} + +void vfs_init() { + fs_list.head = 0; + fs_list.tail = 0; + // init and register tmpfs + tmpfs_init(); + struct filesystem* tmpfs = + (struct filesystem*)malloc(sizeof(struct filesystem)); + tmpfs->name = "tmpfs"; + tmpfs->setup_mount = tmpfs_setup_mount; + register_filesystem(tmpfs); + + // use tmpfs to mount root filesystem + rootfs = (struct mount*)malloc(sizeof(struct mount)); + struct filesystem* fs = get_fs_by_name("tmpfs"); + if (fs == 0) { + // printf("[Error] Mount root filesystem failed!!\n"); + return; + } + fs->setup_mount(fs, rootfs); + current_dir = rootfs->root; + // cpio_populate_rootfs(); + + // init and register cpio + cpiofs_init(); + struct filesystem* cpiofs = + (struct filesystem*)malloc(sizeof(struct filesystem)); + cpiofs->name = "cpiofs"; + cpiofs->setup_mount = cpiofs_setup_mount; + register_filesystem(cpiofs); + + vfs_mkdir("/initramfs"); + vfs_mount("", "/initramfs", "cpiofs"); + + //device + device_init(); + struct filesystem* devfs = + (struct filesystem*)malloc(sizeof(struct filesystem)); + devfs->name = "dev"; + devfs->setup_mount = device_setup_mount; + register_filesystem(devfs); + + vfs_mkdir("/dev"); + vfs_mount("", "/dev", "dev"); + + // init and register fatfs + fatfs_init(); + struct filesystem* fatfs = + (struct filesystem*)malloc(sizeof(struct filesystem)); + fatfs->name = "fatfs"; + fatfs->setup_mount = fatfs_setup_mount; + register_filesystem(fatfs); + + vfs_mkdir("/boot"); + vfs_mount("", "/boot", "fatfs"); +} + +int register_filesystem(struct filesystem* fs) { + // register the file system to the kernel. + if (fs_list.head == 0) { + fs_list.head = fs; + fs_list.head->next = 0; + fs_list.tail = fs_list.head; + } else { + fs_list.tail->next = fs; + fs_list.tail = fs_list.tail->next; + } + return 1; +} + +struct filesystem* get_fs_by_name(const char* name) { + for (struct filesystem* fs = fs_list.head; fs != 0; fs = fs->next) { + if (!strcmp(fs->name, name)) { + return fs; + } + } + // printf("[Error] Filesystem \'%s\' not found!!\n", name); + return 0; +} + +int vfs_find_vnode(struct vnode** target, const char* pathname) { + if (!strcmp(pathname, "/")) { + *target = rootfs->root; + return 1; + } + + char* pathname_ = (char*)malloc(strlen(pathname) + 1); + strcpy(pathname_, pathname); + struct vnode* dir = current_dir; + if (pathname_[0] == '/') dir = rootfs->root; + // printf("[vfs_find_vnode]find node: %s\n", pathname_); + + char* component_name = strtok(pathname_, '/'); + while (component_name && *component_name != '\0') { + int found = dir->v_ops->lookup(dir, target, component_name); + // printf("[vfs_find_vnode]component name: %s, found %d\n", component_name, found); + if (!found) { + printf("[Error] No such file or directory: %s\n", pathname); + free(pathname_); + return 0; + } + if ((*target)->mount) *target = (*target)->mount->root; + dir = *target; + component_name = strtok(0, '/'); + } + free(pathname_); + return 1; +} + +struct file* vfs_open(const char* pathname, int flags) { + // 1. Lookup pathname from the root vnode. + // 2. Create a new file descriptor for this vnode if found. + // 3. Create a new file if O_CREAT is specified in flags. + struct vnode* dir = current_dir; + struct vnode* target = 0; + struct file* file = 0; + + char* pathname_ = (char*)malloc(strlen(pathname) + 1); + strcpy(pathname_, pathname); + // pathname: /mnt -> pathname_: "\0", filename: mnt + // pathname: /mnt/file1 -> pathname_: /mnt, filename: file1 + // pathname: file1 -> pathname_: file1, filename: NULL + char* filename = split_last(pathname_, '/'); + // printf("[vfs_open] pathname_ :%s, filename :%s\n", pathname_, filename); + if (*pathname_ == '\0' && pathname[0] == '/') { + dir = rootfs->root; + } + if (filename != 0) { + int prefix_found = vfs_find_vnode(&dir, pathname_); + // e.g., given pathname /abc/zxc/file1, but /abc/zxc not found + if (!prefix_found) { + printf("[Error] Path does not exist: %s\n", pathname); + free(pathname_); + return 0; + } + } else { + filename = pathname_; + } + + int file_found = dir->v_ops->lookup(dir, &target, filename); + if (flags == O_CREAT) { + printf("[open]CREATE\n"); + if (!file_found) { + dir->v_ops->create(dir, &target, filename, FILE_REGULAR); + file = (struct file*)malloc(sizeof(struct file)); + file->vnode = target; + file->f_ops = target->f_ops; + file->f_pos = 0; + } else { + printf("[Error] File already exists: %s\n", pathname); + } + } else { + if (!file_found) { + printf("[Error] File does not exist: %s\n", pathname); + } else { + if (target->mount) target = target->mount->root; + file = (struct file*)malloc(sizeof(struct file)); + file->vnode = target; + file->f_ops = target->f_ops; + file->f_pos = 0; + } + } + free(pathname_); + return file; +} + +int vfs_close(struct file* file) { + // 1. release the file descriptor + // free(file); + return 1; +} + +int vfs_write(struct file* file, const void* buf, size_t len) { + // 1. write len byte from buf to the opened file. + // 2. return written size or error code if an error occurs. + return file->f_ops->write(file, buf, len); +} + +int vfs_read(struct file* file, void* buf, size_t len) { + // 1. read min(len, readable file data size) byte to buf from the opened file. + // 2. return read size or error code if an error occurs. + return file->f_ops->read(file, buf, len); +} + +int vfs_list(struct file* file, void* buf, int index) { + return file->f_ops->list(file, buf, index); +} + +int vfs_mkdir(const char* pathname) { + // printf("%s\n", pathname); + struct vnode* dir = current_dir; + struct vnode* target = 0; + + char* pathname_ = (char*)malloc(strlen(pathname) + 1); + strcpy(pathname_, pathname); + // pathname: /mnt -> pathname_: "\0", dirname: mnt + // pathname: /mnt/dir1 -> pathname_: /mnt, dirname: dir1 + // pathname: dir1 -> pathname_: dir1, dirname: NULL + char* dirname = split_last(pathname_, '/'); + printf("[vfs_mkdir] pathname_ :%s, dirname :%s\n", pathname_, dirname); + + if (*pathname_ == '\0' && pathname[0] == '/') { + dir = rootfs->root; + } + + if (dirname != 0) { + int prefix_found = vfs_find_vnode(&dir, pathname_); + // e.g., given pathname /abc/zxc/file1, but /abc/zxc not found + if (!prefix_found) { + // printf("[Error] Path does not exist: %s\n", pathname); + free(pathname_); + return 0; + } + } else { + dirname = pathname_; + } + + int file_found = dir->v_ops->lookup(dir, &target, dirname); + if (file_found) { + printf("[Error] File already exists: %s\n", pathname); + return 0; + } + int status = dir->v_ops->create(dir, &target, dirname, FILE_DIRECTORY); + free(pathname_); + return status; +} + +int vfs_chdir(const char* pathname) { + struct vnode* target = 0; + int dir_found = vfs_find_vnode(&target, pathname); + if (!dir_found) { + // printf("[Error] Directory does not exist: %s\n", pathname); + return 0; + } + vnode_print(current_dir); + vnode_print(target); + current_dir = target; + // struct tmpfs_fentry* fentry = (struct tmpfs_fentry*)current_dir->internal; + // printf("[chdir] %s\n", fentry->name); + return 1; +} + +int vfs_mount(const char* device, const char* mountpoint, + const char* filesystem) { + printf("[vfs_mount] %s\n", mountpoint); + struct vnode* target = 0; + int dir_found = vfs_find_vnode(&target, mountpoint); + + if (!dir_found) { + printf("[Error] Directory does not exist: %s\n", mountpoint); + return 0; + } + if (target->mount) { + printf("[Error] This directory has been mounted: %s\n", mountpoint); + return 0; + } + + // find parent_vnode + char* pathname_ = (char*)malloc(strlen(mountpoint) + 5); + strcpy(pathname_, mountpoint); + struct vnode* parent_vnode = 0; + strcat(pathname_, "/.."); + // int parent_found = vfs_find_vnode(&parent_vnode, pathname_); + vfs_find_vnode(&parent_vnode, pathname_); + free(pathname_); + + struct mount* mountfs = (struct mount*)malloc(sizeof(struct mount)); + struct filesystem* fs = get_fs_by_name(filesystem); + fs->setup_mount(fs, mountfs); + + //target is mountpoint + target->mount = mountfs; + mountfs->root->v_ops->set_parent(mountfs->root, parent_vnode); + return 1; +} + +int vfs_umount(const char* mountpoint) { + // printf("[umount] %s\n", mountpoint); + struct vnode* dir = current_dir; + struct vnode* target = 0; + + char* pathname_ = (char*)malloc(strlen(mountpoint) + 1); + strcpy(pathname_, mountpoint); + // pathname: /mnt -> pathname_: "\0", dirname: mnt + // pathname: /mnt/dir1 -> pathname_: /mnt, dirname: dir1 + // pathname: dir1 -> pathname_: dir1, dirname: NULL + char* dirname = split_last(pathname_, '/'); + if (*pathname_ == '\0' && mountpoint[0] == '/') { + dir = rootfs->root; + } + // printf("%s %s\n", pathname_, dirname); + + if (dirname != 0) { + int prefix_found = vfs_find_vnode(&dir, pathname_); + // e.g., given pathname /abc/zxc/file1, but /abc/zxc not found + if (!prefix_found) { + // printf("[Error] Path does not exist: %s\n", mountpoint); + free(pathname_); + return 0; + } + } else { + dirname = pathname_; + } + + int file_found = dir->v_ops->lookup(dir, &target, dirname); + if (!file_found) { + // printf("[Error] Directory does not exist: %s\n", mountpoint); + return 0; + } + + if (!target->mount) { + // printf("[Error] This directory is not mounted: %s\n", mountpoint); + return 0; + } + target->mount = 0; + return 1; +} \ No newline at end of file diff --git a/lab8/make.sh b/lab8/make.sh new file mode 100755 index 000000000..893cdd3e6 --- /dev/null +++ b/lab8/make.sh @@ -0,0 +1,9 @@ +#bin/sh! + +make +cd kernel +make +cd .. +cd bootloader +make +cd .. diff --git a/lab8/qemu_run.sh b/lab8/qemu_run.sh new file mode 100755 index 000000000..4673212bd --- /dev/null +++ b/lab8/qemu_run.sh @@ -0,0 +1,4 @@ +# sudo chmod 777 /dev/ttyUSB0 +# python3 ./script/send_file.py -s bootloader.img +# python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/ttyUSB0 +python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/pts/14 diff --git a/lab8/run.sh b/lab8/run.sh new file mode 100755 index 000000000..a8d89f256 --- /dev/null +++ b/lab8/run.sh @@ -0,0 +1,4 @@ +sudo chmod 777 /dev/ttyUSB0 +# python3 ./script/send_file.py -s bootloader.img +python3 ./script/send_file.py -s kernel/build/kernel8.img -t /dev/ttyUSB0 +# python3 ./script/send_file.py -s kernel8.img -t /dev/pts/9 diff --git a/lab8/script/send_file.py b/lab8/script/send_file.py new file mode 100644 index 000000000..475fab1ec --- /dev/null +++ b/lab8/script/send_file.py @@ -0,0 +1,42 @@ +import argparse +from pathlib import Path +import serial + +def send_all_data(tty, data): + while len(data) > 0: + write_cnt = tty.write(data) + data = data[write_cnt:] + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + "-s", + "--src_file_pth", + type=str, + help='source file path', + default='../kernel8.img' + ) + parser.add_argument( + "-t", + "--target_pth", + nargs='?', + type=str, + help='target path', + default='/dev/ttyUSB0' + ) + args = parser.parse_args() + + with serial.Serial(args.target_pth, 115200, xonxoff=True) as tty: + magic = 0x01020304.to_bytes(4, 'big') + send_all_data(tty, magic) + + file_size = Path(args.src_file_pth).stat().st_size.to_bytes(8, 'little') + send_all_data(tty, file_size) + + with open(args.src_file_pth, 'rb') as src_file: + while True: + data = src_file.read() + if data == b'': + break + send_all_data(tty, data) + print("finish sending kernel8.img\n") \ No newline at end of file diff --git a/lab8/sfn_nctuos.img b/lab8/sfn_nctuos.img new file mode 100644 index 000000000..5138de3e5 Binary files /dev/null and b/lab8/sfn_nctuos.img differ diff --git a/lab8/user/Makefile b/lab8/user/Makefile new file mode 100644 index 000000000..8961cfcb5 --- /dev/null +++ b/lab8/user/Makefile @@ -0,0 +1,32 @@ +CC = aarch64-linux-gnu-gcc +CFLAGS = -Wall -g -ffreestanding -march=armv8-a +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJCOPYFLAGS = -O binary + +BUILD_DIR = build +SRC_DIR = src +C_FILES = $(wildcard $(SRC_DIR)/*.c) +TARGET_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%) +LINKER = $(SRC_DIR)/linker.ld + +all: $(TARGET_FILES) + +clean: + rm $(BUILD_DIR)/* + +$(BUILD_DIR)/%: $(BUILD_DIR)/%.elf + $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ + cp $@ ../kernel/rootfs && \ + cd ../kernel/rootfs && \ + rm -f ../initramfs.cpio && \ + find . | cpio -o -H newc > ../initramfs.cpio + +$(BUILD_DIR)/%.elf: $(BUILD_DIR)/%.o $(BUILD_DIR)/start.asmo + $(LD) -T $(LINKER) --gc-sections -g -o $@ $< $(BUILD_DIR)/start.asmo + +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/start.asmo: $(SRC_DIR)/start.S + $(CC) $(CFLAGS) -c $< -o $@ diff --git a/lab8/user/src/argv_test.c b/lab8/user/src/argv_test.c new file mode 100644 index 000000000..aa9c5bed3 --- /dev/null +++ b/lab8/user/src/argv_test.c @@ -0,0 +1,17 @@ +#include "start.h" + +int main(int argc, char **argv) { + // printf("Argv Test, pid %d\n", getpid()); + print_s("Argv Test, pid "); + print_i(getpid()); + print_s("\n"); + for (int i = 0; i < argc; ++i) { + // puts(argv[i]); + print_s(argv[i]); + print_s("\n"); + } + char *fork_argv[] = {"fork_test", 0}; + exec("fork_test", fork_argv); + + return 0; +} \ No newline at end of file diff --git a/lab8/user/src/fork_test.c b/lab8/user/src/fork_test.c new file mode 100644 index 000000000..a8b65a079 --- /dev/null +++ b/lab8/user/src/fork_test.c @@ -0,0 +1,46 @@ +#include "start.h" + +int main() { + // printf("Fork Test, pid %d\n", getpid()); + print_s("Fork Test, pid "); + print_i(getpid()); + print_s("\n"); + int cnt = 1; + int ret = 0; + if ((ret = fork()) == 0) { // child + // printf("pid: %d, cnt: %d, ptr: %p\n", getpid(), cnt, &cnt); + print_s("pid: "); + print_i(getpid()); + print_s(", cnt: "); + print_i(cnt); + print_s(", ptr: "); + print_h((unsigned long long)&cnt); + print_s("\n"); + ++cnt; + fork(); + while (cnt < 5) { + // printf("pid: %d, cnt: %d, ptr: %p\n", getpid(), cnt, &cnt); + print_s("pid: "); + print_i(getpid()); + print_s(", cnt: "); + print_i(cnt); + print_s(", ptr: "); + print_h((unsigned long long)&cnt); + print_s("\n"); + delay(1000000000); + ++cnt; + } + } else { + // printf("parent here, pid %d, child %d\n", getpid(), ret); + for(int i = 0 ; i < 5;i++){ + print_s("parent here, pid: "); + print_i(getpid()); + print_s(", child: "); + print_i(ret); + print_s("\n"); + delay(1000000000); + } + } + // while(1); + return 0; +} \ No newline at end of file diff --git a/lab8/user/src/linker.ld b/lab8/user/src/linker.ld new file mode 100644 index 000000000..8e6ab1c9d --- /dev/null +++ b/lab8/user/src/linker.ld @@ -0,0 +1,17 @@ +SECTIONS +{ + . = 0x80000; + + .text : { KEEP(*(.text.boot)) *(.text .text.*) } + + .rodata : { *(.rodata .rodata.*) } + + .data : { *(.data .data.*) } + + .bss : { + *(.bss .bss.*) + *(COMMON) + } + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} \ No newline at end of file diff --git a/lab8/user/src/my_test.c b/lab8/user/src/my_test.c new file mode 100644 index 000000000..ef5620ae8 --- /dev/null +++ b/lab8/user/src/my_test.c @@ -0,0 +1,12 @@ +#include "start.h" +int main(int argc, char **argv) { + for(int i = 0 ; i<10 ; i++){ + print_s("Test1, pid "); + print_i(getpid()); + print_s("\n"); + delay(1000000000); + // asm volatile("mov x8, #9"); + // asm volatile("svc 0"); + } + return 0; +} \ No newline at end of file diff --git a/lab8/user/src/my_test2.c b/lab8/user/src/my_test2.c new file mode 100644 index 000000000..8024d8bbd --- /dev/null +++ b/lab8/user/src/my_test2.c @@ -0,0 +1,12 @@ +#include "start.h" +int main(int argc, char **argv) { + for(int i = 0 ; i<10 ; i++){ + print_s("Test2, pid "); + print_i(getpid()); + print_s("\n"); + delay(1000000000); + // asm volatile("mov x8, #9"); + // asm volatile("svc 0"); + } + return 0 ; +} \ No newline at end of file diff --git a/lab8/user/src/start.S b/lab8/user/src/start.S new file mode 100644 index 000000000..fc5a50624 --- /dev/null +++ b/lab8/user/src/start.S @@ -0,0 +1,49 @@ +.section ".text.boot" + +.global _start + +_start: + bl main + b exit + +.section ".text" + +.global uart_read +.global uart_write +.global getpid +.global fork +.global exec +.global exit + +getpid: + mov x8, #0 + svc 0 + ret + +uart_read: + mov x8, #1 + svc 0 + ret + +uart_write: + mov x8, #2 + svc 0 + ret + +exec: + mov x8, #3 + svc 0 + ret + +fork: + mov x8, #4 + svc 0 + ret + +exit: + mov x8, #5 + svc 0 + ret + + + diff --git a/lab8/user/src/start.h b/lab8/user/src/start.h new file mode 100644 index 000000000..24468b7ca --- /dev/null +++ b/lab8/user/src/start.h @@ -0,0 +1,54 @@ +#ifndef START_H +#define START_H + +#include +#include + +unsigned long uart_read(char buf[], size_t size); +unsigned long uart_write(const char buf[], size_t size); +int getpid(); +unsigned long fork(); +int exec(const char *name, char *const argv[]); +void exit(); + +void delay(int n) { + while (n--) + ; +} + +int strlen(const char *s) { + int len = 0; + while (s[len] != '\0') { + len++; + } + return len; +} + +void print_c(char c) { + char s[2]; + s[0] = c; + s[1] = '\0'; + uart_write(s, strlen(s)); +} + +void print_s(char *s) { uart_write(s, strlen(s)); } + +void print_i(int x) { + if (x < 0) { + print_c('-'); + x = -x; + } + if (x >= 10) print_i(x / 10); + print_c(x % 10 + '0'); +} + +void print_h(unsigned long x) { + print_s("0x"); + for (int c = 28; c >= 0; c -= 4) { + int n = (x >> c) & 0xF; + n += n > 9 ? 'A' - 10 : '0'; + print_c(n); + } +} + +#endif \ No newline at end of file diff --git a/lab8/user/src/svc_test.c b/lab8/user/src/svc_test.c new file mode 100644 index 000000000..a3fbfe8dd --- /dev/null +++ b/lab8/user/src/svc_test.c @@ -0,0 +1,7 @@ +int main() { + for (int i = 0; i < 5; i++) { + asm volatile("svc 0"); + } + + return 0; +} \ No newline at end of file diff --git a/lab8/user/src/user_program.S b/lab8/user/src/user_program.S new file mode 100644 index 000000000..838323763 --- /dev/null +++ b/lab8/user/src/user_program.S @@ -0,0 +1,11 @@ +.section ".text" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b \ No newline at end of file